java - String的intern方法的疑问
天蓬老师
天蓬老师 2017-04-18 10:06:31
0
1
818
天蓬老师
天蓬老师

欢迎选择我的课程,让我们一起见证您的进步~~

全部回覆(1)
巴扎黑

上面的程式碼, 我用 JDK6 和 JDK7 分別運行了一下, 結果如下:

JDK6: false, false
JDK7: false, false

沒有如題主所說的是 true, false. 我想究其原因, 主要有兩點:

  • 字串 "java" 比較特殊, 它在常數池中固定存在的

因此代碼

String str1 = new StringBuilder("ja").append("va").toString();
System.out.println(str1.intern() == str1);

str1.intern() 回傳的是常數池中的物件, 於是和堆上的 str1 就不是同一個物件了.

  • "python" 字串已經在程式碼中出現了, 因此會加入到常數池中.

第二部分的程式碼中, 因為出現了字面常數 "python", 因此它會添加到常數池中.
而:

String str2 = new StringBuilder("python").append("").toString();
System.out.println(str2.intern() == str2);

為字串 "python" 新增了空字串 "", 因此相當於沒有新增的字串常數, 進而 str2.intern() 傳回的還是常數池中的物件.


其實上面的題目可以引申一下, 例如:

// 1
String str1 = new StringBuilder("ja").append("va1").toString();
System.out.println(str1.intern() == str1); // true
// 2
String str2 = new StringBuilder("python").append("").toString();
System.out.println(str2.intern() == str2); // false

我只把第一部分的程式碼"StringBuilder("ja").append("va")" 改為"StringBuilder("ja").append("va1")". 這樣改動會有什麼不同的結果嗎?
我們來看看在JDK6 和JDK7 下運行的結果吧:

JDK6: false, false
JDK7: true, false

為什麼 JDK6 和 JDK7 的運行結果不一樣呢?
其實這涉及到了不同的 JDK 對 intern() 方法的不同實現:
在 JDK6 及以前的 JDK 中:

intern() 方法会把首次遇到的字符串实例 **复制** 到永久代中, 然后返回永久代中的实例.

而對於 JDK7 以及之上的JDK:

当遇到第一次出现的字符串时, intern() **不再复制实例**, 而是在常量池中记录首次出现的实例的引用, 并且 intern() 返回的是此实例引用.

根據 JDK6 和 JDK7 的 intern() 方法的區別, 我們就知道了例子:

// 1
String str1 = new StringBuilder("ja").append("va1").toString();
System.out.println(str1.intern() == str1); // true
// 2
String str2 = new StringBuilder("python").append("").toString();
System.out.println(str2.intern() == str2); // false

在不同的JDK 回傳不同結果的原因了:
在JDK6 中, "java1" 是第一次出現的字串常數, 因此會被複製到常數池中, intern() 方法傳回的是常數池中的物件, 因此與堆上的str1 就不等了.
而在JDK7 中, "java1" 是第一次出現的字串常數, 但是intern() 方法僅僅是將這個物件的引用添加到常數池中,並沒有像JDK6 一樣拷貝一個新物件到常數池, 因此intern() 方法返回的引用其實還是和原來的str1 相等.

熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板