🥰🥰🥰來都來了,不妨點個關注叭!
👉博客主頁:歡迎各位大佬!👈
文章目錄
- 1. 字符串不可變性
- 1.1 設計不可變
- 1.2 修改字符串創建新對象
- 1.3 為什么字符串不可變
- 1.4 String類設計不可變的好處
- 1.5 字符串的修改
- 2. 如何查看反編碼?
- 3. StringBuff和StringBuilder
- 4. 常考面試題
1. 字符串不可變性
String是一種不可變對象,即字符串中的內容是不可改變,它們的內容被創建好后,就不能被修改了!
為什么呢~
1.1 設計不可變
String類在設計時是不可改變,String類實現描述中已說明,以下來自JDK1.8String類的部分實現,如下圖:
1)String類中的字符實際保存在內部維護的value字符數組中
2)String類被?nal修飾,表示String類不能被繼承
3)value被?nal修飾,表示value自身的值不能改變,即不能引用其它字符數組,但其引用空間中的內容可以修改
1.2 修改字符串創建新對象
所有涉及到可能修改字符串內容的操作都是創建一個新對象,改變的是新對象
字符串的不可變性,字符串中的內容是不可改變,如修改了則是創建了新對象,改變的是新對象
1.3 為什么字符串不可變
【誤區】
認為字符串不可變是因為其內部保存字符的數組value被?nal修飾了,因此不能改變
這種說法是錯誤的,不是因為String類自身被final修飾,也不是因為其內部value被?nal修飾而不能被修改
【正解】
?nal修飾類表明該類不想被繼承,?nal修飾引用類型表明該引用變量不能引用其他對象,但其引用對象中的內容可以修改,“看起來String可變”,其實創建了新對象!!!
public class Test17 {public static void main(String[] args) {final int array[] = {1,2,3,4,5};array[0] = 100;System.out.println(Arrays.toString(array));array = new int[]{7,8,9};// 編譯報錯:Error:(15, 9) java: 無法為最終變量array分配值}
}
由上述代碼進一步理解:可以修改對象引用的內容,但是無法更改引用的指向!!!
1.4 String類設計不可變的好處
為什么String類要設計成不可變的呢~
原因有以下3點:
- 從字符串對象池來說,方便實現字符串對象池,如果 String 可變,對象池就需要考慮寫時拷貝的問題,變得復雜
- 從線程安全角度來說,不可變對象是線程安全的
- 從緩存角度來說,不可變對象更方便緩存 hash code, 作為 key 時可以更高效的保存到 HashMap中
1.5 字符串的修改
以下這種方式不推薦使用!!!
【原因】效率極低,中間創建好多臨時對象,空間的占用
public class Test {public static void main(String[] args) {String s = "hello ";s += "world!";System.out.println(s);}
}
打印結果如下:
在上述代碼過程中,查看反編碼,具體過程分析如下圖:
StringBuilder的構造方法如下:
可想而知,如果放在循環體中這樣修改字符串,中間會創建好多臨時變量
【注意】盡量避免直接對String類型對象進行修改,String類不能修改,所有的修改都會創建新對象,效率非常低
String類進行修改時,效率非常慢,所以需要盡量避免對String的直接使用修改,如果要修改建議盡量使用StringBu?er或者StringBuilder,接下來StringBu?er和StringBuilder閃亮登場!
2. 如何查看反編碼?
上面的反編碼是如何進行查看的呢?下面是保姆級教程!!!
【步驟】
1)首先運行該程序!!!
2)找到文件所在位置
3)找到字節碼文件
進入到這個界面,我們需要找到.class文件,即字節碼文件
4 )輸入cmd
5)輸入 javap -c Test15
【注意事項】javap -c Test15中Test15是該程序的類名,請輸入你自己的類名哦~
3. StringBuff和StringBuilder
由于String的不可更改特性,為方便字符串的修改,Java中又提供StringBuilder和StringBu?er類這兩大類,這兩個類大部分功能是相同的
這里介紹 StringBuilder和StringBuff常用的一些方法:
其它方法需要用到可參閱Java在線文檔
以下為上述方法的具體使用,更深入了解其方法~
public class Test {public static void main(String[] args) {StringBuilder sb1 = new StringBuilder("hello");StringBuilder sb2 = sb1;//append追加即尾插(字符、字符串、整形數字)sb1.append(' '); //hellosb1.append("world"); //hello worldsb1.append(1); //hello world1System.out.println(sb1); //hello world1System.out.println(sb1 == sb2); //trueSystem.out.println(sb1.length()); //獲取字符串的有效長度12System.out.println(sb1.capacity()); //獲取底層數組的總大小sb1.setCharAt(0, 'H'); //設置任意位置的字符 Hello world1sb1.insert(0, "Hello world!!!"); //Hello world!!!Hello world1System.out.println(sb1);System.out.println(sb1.indexOf("Hello")); //獲取Hello第一次出現的位置System.out.println(sb1.lastIndexOf("hello")); //獲取hello最后一次出現的位置sb1.deleteCharAt(0); //刪除首字符sb1.delete(0,5); //刪除[0, 5)范圍內的字符String str = sb1.substring(0, 5); //截取[0, 5)區間中的字符以String的方式返回System.out.println(str);sb1.reverse(); //字符串逆轉str = sb1.toString(); //將StringBu?er以String的方式返回System.out.println(str);}
}
在很多題目中,StringBuilde.append()方法經常使用到,應用于那些經常要修改的字符串中,還是相當方便噠~
【注意事項】
String和StringBuilder類不能直接轉換。如果想互相轉換,采用如下原則:
String—>StringBuilder: 1)利用StringBuilder的構造方法 2) append()方法
StringBuilder—>String: 調用toString()方法
4. 常考面試題
String、StringBu?er、StringBuilder的區別
- 內容上,String的內容不可修改,StringBu?er與StringBuilder的內容可以修改
- 功能上,StringBu?er與StringBuilder大部分功能是相似的
- 線程安全上,StringBu?er采用同步處理,屬于線程安全操作;而StringBuilder未采用同步處理,屬于線程不安全操作
【解釋說明】
對線程安全來說,StringBu?er線程安全,可以在多線程下使用,StringBuilder線程不安全在單線程下使用,那么都用StringBu?er不就好了嘛~不需要考慮線程安全問題了
不行!!!會浪費很多資源,加鎖和釋放鎖都會浪費資源!
💛💛💛本期內容回顧💛💛💛
???本期內容到此結束啦~