String類不能被繼承
通過源碼可以看到String類前面加了final修飾,因此String類是不能夠被繼承的。將其設(shè)置為不能被繼承的原因是為了減少歧義。
字符串(String)的不可變性
String創(chuàng)建好之后值是不可以被改變的,這里指的是在堆中的字符串的值是不可以被改變。
示例

String是引用數(shù)據(jù)類型,但是這里作為方法參數(shù)傳遞的時候,效果跟基本數(shù)據(jù)類型是一樣的。也就是說在堆中創(chuàng)建出來的字符串”monkey”是不能被改變的,如果要修改,系統(tǒng)會在堆中重新開辟內(nèi)存空間將”good”放入,然后將change方法中的s重新引用這個新的內(nèi)存地址上的”good”。
String不可變的主要原因是其底層使用了一個final修飾的byte數(shù)組(jdk9之后版本中),final修飾的變量是不能被改變的。在jdk8版本中,String底層使用的是final修飾的char數(shù)組。這個版本之間的變化。

字符串常量池
我們聲明的字符串會放到一個叫做字符串常量池的地方,這樣可以減少內(nèi)存的使用,字符串常量池是堆的一部分。

上面代碼中,創(chuàng)建s1時,字符串常量池中還不存在堆中monkey的引用,因此jvm會在常量池中創(chuàng)建一個引用指向堆中的這個字符串對象,創(chuàng)建s2時,jvm會去常量池中搜索,此時常量池中有monkey的引用,所以就不創(chuàng)建了,直接讓s2指向之前創(chuàng)建的monkey,所以s1和s2指向的是同一個堆內(nèi)存中的對象。
創(chuàng)建s3時,因為使用了new關(guān)鍵字,所以會在堆中開辟一塊內(nèi)存地址將其放入,s3指向這個新的內(nèi)存地址,所以s3和s1指向的不是同一個內(nèi)存地址。
創(chuàng)建s4時,使用了new關(guān)鍵字,會在堆中開辟一塊內(nèi)存地址,s4指向這個內(nèi)存地址,然后字符串常量池中沒有指向good的引用,所以會再重新開辟一塊空間,將good放入,然后在字符串常量池中指向這個地址。
開發(fā)中建議使用String s = “monkey1024”;這種方式創(chuàng)建字符串對象,可以減少堆內(nèi)存的使用。
注意:比較兩個字符串是否一致最好使用equals方法

String類常用方法
char charAt(int index);獲取index位置的字符
boolean contains(CharSequence s);判斷字符串中是否包含某個字符串
boolean endsWith(String endStr);判斷是否是以某個字符串結(jié)尾
boolean equalsIgnoreCase(String anotherString);忽略大小寫比較兩個字符串是否相等
byte[] getBytes();轉(zhuǎn)換成byte數(shù)組
int indexOf(String str);取得指定字符在字符串的位置
int indexOf(String str, int fromIndex);從指定的下標(biāo)開始取得指定字符在字符串的位置
int lastIndexOf(String str);從后面開始取得指定字符在字符串最后出現(xiàn)的的位置
int length();獲取字符串的長度
String replaceAll(String s1,String s2);替換字符串中的內(nèi)容
String[] split(String s);根據(jù)指定的表達(dá)式拆分字符串
boolean startsWith(String s);判斷是否是以某個字符串開始
String substring(int begin);根據(jù)傳入的索引位置截子串
String substring(int beginIndex, int endIndex);根據(jù)傳入的起始和結(jié)束位置截子串
char[] toCharArray();將字符串轉(zhuǎn)換為char數(shù)組
void toUpperCase();轉(zhuǎn)換為大寫
void toLowerCase();轉(zhuǎn)換為小寫
String trim();去除首尾空格
String valueOf(Object obj);將其他類型轉(zhuǎn)換為字符串類型
