new一個String對象的時候,如果常量池沒有相應的字面量真的會去它那裡創建一個嗎?我表示懷疑。


這個問題已經被充分討論過。我想寫的以前都寫過了所以只放傳送門:答覆:發現String#intern的API描述有問題

至於說:

之前一直有個結論就是:當創建一個string對象的時候,去字元串常量池看是否有相應的字面量,如果沒有就創建一個。

這個說法從來都不正確。


① 使用字元串直接量時會在常量池創建對象,當然必須是常量摺疊之後的。

② 使用new String()時,new產生的字元串對象是位於堆中,而不是常量池中。

③ JDK7之後intern()發生過變化,現在如果常量池中不存在這個對像,不會複製到常量池中,而是簡單的使用堆中已有字元串對象。

④ JDK7以前的intern()不是這樣子的,以前會在常量池中創建一個新的對象,你可以將你的代碼,在JDK6中測試一下,結果應該會不同。

所以,你的問題不在new String()上,而是在intern()上,前者與常量池從來就沒有關係。


你把a從控制台里讀進來再試試看。


很多人都把字元串常量池,運行時常量池,Class文件常量池混為一談,這裡給大家區分一下這幾個概念大家就會徹底明白這類的問題了。

Java中幾種常量池的區分 // Emanuel"s Notes


看了你最後一個例子,自己親自測試了一下:

public static void pushPool() {
String a = "a";
String param = "b" + a;
System.out.println("ba" == param.intern());
System.out.println(param == "ba");
}

首先param使用了jdk的內部優化,使用了Stringbuilder構造的(java編程思想中講過),然後調用StringBuilder的toString(),toString()方法如下:

public String toString() {
// Create a copy, don"t share the array
return new String(value, 0, count);
}


param執行intern後本身就會變成指向常量池,把一個常量池string賦值給paramsame,兩者都指向常量池,當然==結果為true。


總結之後,其實原因就是,對字元串字面量的引用,返回的是上一次對此字面量引用返回的對象引用。如果是第一次引用,則返回一個對象引用,並為此對象調用intern方法,以後每次引用此字面量,返回的都是這個對象引用。


這是jdk7中intern()函數的新變化,樓主可以去看看周志明的《深入理解java虛擬機》,裡面說的非常清楚


推薦閱讀:

C++ 如何從函數中返回數組的引用並且該數組包含 10 個 string 對象?

TAG:Java虛擬機JVM | string |