1.方法intern()爲java內部方法,如下
public native String intern();
native方法爲通過jvm進行運行,jdk8中隱藏了該方法的具體處理方法。
2.作用:該方法註釋爲
“如果常量池中存在當前字符串, 就會直接返回當前字符串. 如果常量池中沒有此字符串, 會將此字符串放入常量池中後, 再返回”。
3.測試代碼一
public static void main(String[] args) { String s1 = new String("1"); s1.intern(); String s2 = "1"; System.out.println(s1 == s2); String s3 = new String("1") + new String("1"); s3.intern(); String s4 = "11"; System.out.println(s3 == s4); }
結果:
jdk6環境下:
false false
jdk8環境下:
false true
原因分析:
1)jdk6的虛擬機結構中常量池主要是在Perm中,即內存模型爲對象存放到java堆區(heap)中,而常量池主要是在java方法區。屬於不同的兩個區域。
字符串的初始化中,new時會創建一個對象放在java堆中,而通過引號創建則會在常量池中創建常量,兩個區域是隔絕的,因此即使intern之後比較引用的話也不會是相同的。
2)jdk7之後由於之前Perm的大小隻有4M,已經無法滿足項目的發展,因此取消了Perm的限制,而是移動到了堆區,jdk8更是取消了Perm區。
對於上面代碼,s1創建的時候,生成了一個對象和一個對象的值,因此s1對應的是對象的引用,s2是對應的常量的引用。
s3初始化的時候對於“11”來說只有一個對象,當調用intern的時候,由於沒有該常量,因此jdk7之後會生成一個指向對象的引用存放到常量中。而當s4初始化之後,s4也直接爲常量中的對象的引用,因此引用值比較之後爲true。