結構圖:
java
public static void test1() { String str1 = "abc"; String str2 = "abc"; System.out.println(str1==str2); System.out.println(str1==str2.intern()); System.out.println(str1.intern()==str2.intern()); }
結果:true,true,true
數組
例2 :
結構圖:
spa
public static void test1() { String str1 = "abc"; String str2 = new String("abc"); System.out.println(str1==str2); System.out.println(str1==str2.intern()); System.out.println(str1.intern()==str2.intern()); }結果:false,true,true
例3:
結構圖:
code
public static void test3() { String str1 = new String("abc"); String str2 = new String("abc"); System.out.println(str1==str2); System.out.println(str1==str2.intern()); System.out.println(str1.intern()==str2.intern()); }
結果:false,false,true 對象
結果說明:
若是變量直接引用常量池的字符串,那麼結果就會一致。但若是變量引用對象是一個字符串實例,而該實例纔去引用常量池的字符串,那麼比較的結果就不一致。而使用方法intern,就是去取得常量池中的引用
擴展:---------------------------------- 內存
第一點: 字符串
在jdk6中,字符串由三部分組成:char[] , offset , count。由於這樣的結構致使在使用String.substring這個方法時可能發生內存泄漏例: string
String str1 = "abcd...." //假設str1有1萬個字符,同時char[]的長度也有1萬 String str2 = str1.substring(0,1) //str2只想要一個字符,但substring方法並無建立出一個新的字符串常量, //只是在str1基礎上改變了它的偏移量,這彷佛看起來很不錯,由於str1與str2共用char[]節約了內存。 str1 = null; //這時釋放了str1,可是str1的實例並不會被GC回收,由於str2佔有着它,而str2理論上 //應該只有1字符大小的空間,但實際不是,它佔着一萬個字符大小的內存.而在jdk7中它的結構變了,去掉了offset 與count 兩項,String內容由char[]決定,而數組自己也表明了String的值
第二點: class
在jdk6中String常量池是放在perm中,而jdk7中常量池是放在堆中。GC在進行Full GC(不常常觸發)纔會回收perm的內存空間,可是堆的回收(特指年輕代)倒是比較常常發生的
test