首頁  >  問答  >  主體

java - String的intern方法的疑问

天蓬老师天蓬老师2728 天前775

全部回覆(1)我來回復

  • 巴扎黑

    巴扎黑2017-04-18 10:08:31

    上面的程式碼, 我用 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 相等.

    回覆
    0
  • 取消回覆