package string;
public class StringInternMethodPractice {
public static void main(String[] args) {
// append操作在堆內(nèi)存中的字符數(shù)組
StringBuilder stringBuilder1 = new StringBuilder("計算機(jī)").append("軟件");
// toString()將StringBuilder對象里的數(shù)組拷貝一份到String對象里頭的數(shù)組
String str1 = stringBuilder1.toString();
System.out.println(str1.intern() == str1);
StringBuilder stringBuilder2 = new StringBuilder("Ja").append("va");
String str2 = stringBuilder2.toString();
System.out.println(str2.intern() == str2);
}
}
結(jié)果:
JDK6下輸出false false ;JDK7下運(yùn)行輸出 true false
分析
1、JDK6,字符串常量池實現(xiàn)在永久代,intern()方法會把首次遇到的字符串實例復(fù)制到字符串常量池,返回的也是永久代里面這個字符串實例的引用。
調(diào)用str1的intern()方法,由于“計算機(jī)軟件”這個位于堆的字符串首次出現(xiàn),所以將該字符串實例復(fù)制到字符串常量池,并將字符串常量池的字符串實例引用返回。但是str1指向字符串實例在堆內(nèi)存,所以兩者比較為false。
Java這個位于堆的字符串不是首次出現(xiàn),調(diào)用str2的intern()方法,就不需要復(fù)制了,返回永久代里面這個字符串實例的引用。所以兩者比較為false。
2、JDK7,字符串常量池實現(xiàn)在堆中,intern()方法只需要在字符串常量池里記錄一下首次出現(xiàn)的實例引用即可,不需要復(fù)制字符串。
調(diào)用str1的intern()方法,由于“計算機(jī)軟件”這個位于堆的字符串首次出現(xiàn),在字符串常量池里記錄該對象的引用,并返回堆中該字符串實例的引用。所以兩者比較為true。
Java這個位于堆的字符串不是首次出現(xiàn),直接返回已經(jīng)記錄在字符串常量池里該對象的引用,雖然都是堆中的對象引用,但是不是同一個對象,所以返回false。