標籤:
1、Integer
public static void main(String[]args) { Integer i=new Integer(1); System.out.println(i.intValue()); i=2; System.out.println(i.intValue());}
我們知道Integer的屬性value的類型為:final int value;
而方法intValue就是返回value。
很顯然,上面兩次列印結果是不同的,而都是同一個引用變數i。然道我們對置為1的Integer執行個體做了修改,將其value值變成了2?
很顯然,這種結論是不正確的,因為它違反了final修飾變數的特性。
1 public class Test {2 public static void main(String[]args) {3 Integer i=new Integer(1); 4 System.out.println(System.identityHashCode(i));5 i=2;6 System.out.println(System.identityHashCode(i));7 }8 }
通過這段代碼,可知,value值為1的執行個體和value值為2的執行個體是兩個不同的執行個體。正如上說,因為value屬性是由final修飾的,因此這個類是不可變的。
記憶體空間釋義圖如下:
由釋義圖可知,改變了value值,其實就是新產生了一個空間,改變引用變數的指示方向;而原先那個value值為1的執行個體就變成了游離的執行個體,成為java虛擬機器回收的對象目標。正因為,要想改變value就得重啟一個空間,這是比較消耗效能的,因此Integer會對[-128,127]範圍類的值的執行個體緩衝下來。
2、String
其屬性類型為final char value[];
因此String類也是不可變的。
和Integer一樣,改變value值就得新開闢一個空間,這也是效能上的一種消耗,因此,Java給String的字面量也提供了緩衝,如果某個字串的字面量能夠
在緩衝池當中找到那麼就會複用(編譯階段完成的)。
1 public static void main(String[]args) { 2 String str1="feijishuo"; 3 String str2="feijishuo"; 4 System.out.println(str1==str2); //true 5 6 String str3="feiji"; 7 String str4="fei"; 8 String str5="ji"; 9 String str6="fei"+"ji";10 String str7=str4+str5;11 System.out.println(str3==str6); //true12 System.out.println(str3==str7); //false
13
14 final String Str8="fei";
15 String str9=str8+"ji";
16 System.out.println(str3==str9); //true
17 }
程式碼分析:str1和str2指向同一個執行個體,那是因為字面相同,它們會存在於緩衝池(編譯時間常量池)當中。
str3和str6指向同一個執行個體,因為字面量“fei”和“ji”在編譯時間就確定下來了,那麼str6在編譯時間候也能確定下來,然後這個字面量已經在
緩衝池(編譯時間常量池)當中存在了,因此就不用產生新的執行個體了,只要將引用變數指向存在的執行個體即可。
str3和str7不是同一個執行個體,因為變數只有在運行期間才能知道其所指示的值。
str3和str9是同一個執行個體,因為變數str8定義為final類型的,因此其在編譯期間就能確定下來。其執行個體已經存在常量池(編譯時間常量池)當中
存在,因此不會產生新的執行個體。於是,構成str9的式子都能在編譯期間在常量池中找到,因此str9在編譯期間也就確定了下來,其執行個體在常量池中已經存 在。
java的不可變類