深入理解java虛擬機(一):java內存區域(內存結構劃分)
深入理解java虛擬機(二):java內存溢出實戰
深入理解java虛擬機(三):String.intern()-字符串常量池
深入理解java虛擬機(四):對象存活判定算法和垃圾收集算法
深入理解java虛擬機(五):hotspot垃圾收集算法實現
深入理解java虛擬機(六):java垃圾收集分析實戰(內存分配與回收策略)
深入理解java虛擬機(七):java垃圾收集分析總結
深入理解java虛擬機(八):java內存分析工具-MAT和OQL
看源碼:
public native String intern();
Returns a canonical representation for the string object.
A pool of strings, initially empty, is maintained privately by the class String.
When the intern method is invoked, if the pool already contains a string equal to this String object as determined by the equals(Object) method, then the string from the pool is returned. Otherwise, this String object is added to the pool and a reference to this String object is returned.
It follows that for any two strings s and t, s.intern() == t.intern() is true if and only if s.equals(t) is true.
All literal strings and string-valued constant expressions are interned. String literals are defined in §3.10.5 of the Java Language Specification
Returns:
a string that has the same contents as this string, but is guaranteed to be from a pool of unique strings.
意思是說當調用 intern 方法時,如果池已經包含一個等於此 String 對象的字符串(該對象由 equals(Object) 方法確定),則返回池中的字符串。否則,將此 String 對象添加到池中,並且返回此 String 對象的引用。
看下面這段代碼:
public class StringInternTest {
public static void main(String[] args) {
String str1 = new StringBuilder("chaofan").append("wei").toString();
System.out.println(str1.intern() == str1);
String str2 = new StringBuilder("ja").append("va").toString();
System.out.println(str2.intern() == str2);
}
}
有圖可知,當在jdk1.6中運行時,會得到兩個false,而在jdk1.7中運行,會得到一個true和一個false。
產生的差異在於在jdk1.6中 intern 方法會把首次遇到的字符串實例複製到永久待(常量池)中,並返回此引用;但在jdk1.7中,只是會把首次遇到的字符串實例的引用添加到常量池中(沒有複製),並返回此引用。
所以在jdk1.7中執行上面代碼,str1返回true是引用他們指向的都是str1對象(堆中)(池中不存在,返回原引用),而str2返回false是因爲池中已經存在"java"了(關鍵詞),所以返回的池的對象,因此不相等。
看下面實例:
@Test
public void test3(){
String str1 = "a";
String str2 = "b";
String str3 = "ab";
String str4 = str1 + str2;
String str5 = new String("ab");
System.out.println(str5.equals(str3));//true
System.out.println(str5 == str3);//false
System.out.println(str5.intern() == str3);//true
System.out.println(str5.intern() == str4);//false
}
@Test
public void test4(){
String a = new String("ab");
String b = new String("ab");
String c = "ab";
String d = "a" + "b";
String e = "b";
String f = "a" + e;
System.out.println(b.intern() == a);//fasle
System.out.println(b.intern() == c);//true
System.out.println(b.intern() == d);//true 編譯期d已確定(修改、賦值)爲ab
System.out.println(b.intern() == f);//false
System.out.println(b.intern() == a.intern());//true
}
@Test
public void test5(){
// 編譯期已確定
String a = "abc";
String b = "abc";
String c = "a" + "b" + "c";
String d = "a" + "bc";
String e = "ab" + "c";
System.out.println(a == b);//true
System.out.println(a == c);//true
System.out.println(a == d);//true
System.out.println(a == e);//true
System.out.println(c == d);//true
System.out.println(c == e);//true
}