Java 深究字串String類(1)之運算子"+"過載
一.不可改變String
String物件是不可改變的,
檢視JDK文件,發現String類中每一個看似修改String的方法,實際上都建立了一個新的String物件,而最初的String物件則絲毫未動.java傳遞引數的時候,傳遞的是引用的一個拷貝,呼叫時,都會複製一份引用,而引用所指向的物件,一直呆在某一單一物理位置,從未變動過.
二.過載 “+” 與 StringBuilder
String物件是不可改變的,你可以給一個String物件加任意多的別名.
String物件是隻讀的,所要指向它的任何引用都不可能改變它的值.so不會對其他引用產生什麼卵影響.
用於String類中的”+” / “+=” 是Java中僅有的兩個過載過的操作符,而java並不允許我們過載任何操作符;
public class one {
public static void main(String[] args) {
String a = "abc";
String b = "123" + a + "def" + 777;
System.out.println(b);
}
}
如上程式碼,可能這樣工作:
String有append方法,然後返回一個新的String物件的引用,以包含連線後的字串,然後再append , 再建立新物件.
這種方式當然行得通,但是為了生成最終的String,次方式會產生一堆需要垃圾回收的中間物件.然後發現其效能略lowBi.那麼編譯器真的會這樣做嗎?
來來~~,反編譯生成的.class
javap -c one.class
這是JDK自帶的工具 javap -c引數生成位元組碼
懂點彙編就行,,dup,invokevirtural 就是jvm上的彙編.
看好了:
6: dup
7: invokespecial #4 // Method java/lang/StringBuilder.””:()V
10: ldc #5 // String 123
12: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
編譯器自動引用java.lang.StringBuilder類,用以構造最終的String,為每個”+”呼叫一次append方法,最後呼叫toString方法生成最終的String並儲存
三.what if 在迴圈裡使用”+”呢
經過實驗發現:
1.這樣寫:
String str = "";
for(int i = 0; i < num; i++)
{
str += "a";
}
javap -c
5~33是迴圈體, 15句建立一個StringBuilder物件
可知StringBuilder在迴圈體內構建,每次迴圈,建立新的StringBuilder
2.這樣寫:
StringBuilder a = new StringBuilder();
for(int i = 0; i < 10; i++)
{
a.append(i); //只有String能"+"
}
只建立一個StringBuilder類
所以以後寫的時候就知道咋回事了.