做實際參數。如果我通過String
字面一些metohd爲:凡在Java軟件商店
String s=new String("stack");
String s2=s.concat("overflow");
將在其中存儲字符串「溢出」。
我的一個朋友爭辯說,它創建在String
不斷池,我反對他。
請讓我知道
在此先感謝。
做實際參數。如果我通過String
字面一些metohd爲:凡在Java軟件商店
String s=new String("stack");
String s2=s.concat("overflow");
將在其中存儲字符串「溢出」。
我的一個朋友爭辯說,它創建在String
不斷池,我反對他。
請讓我知道
在此先感謝。
全部String
文字會進入常量池。結束。在這種情況下,兩個常量"stack"
和"overflow"
進入池中。創建一個新的String
,它與池中的"stack"
保持相同的值,然後通過將常量池中的"overflow"
連接到它創建另一個String
。
摘自javap -c -verbose Test
:
Constant pool:
#1 = Methodref #10.#19 // java/lang/Object."<init>":()V
#2 = Class #20 // java/lang/String
#3 = String #21 // stack
#4 = Methodref #2.#22 // java/lang/String."<init>":(Ljava/lang/String;)V
#5 = String #23 // overflow
#6 = Methodref #2.#24 // java/lang/String.concat:(Ljava/lang/String;)Ljava/lang/String;
JLS的相關部分:http://docs.oracle.com/javase/specs/jls/se7/html/jls-3.html#jls-3.10.5 - 「此外,字符串常常指向相同的這是因爲字符串文字 - 或者更一般地說,是常量表達式(§15.28)值的字符串 - 被「interned」,以便使用方法String.intern共享唯一實例。 – davmac
@davmac我實際上編譯了這段代碼,因爲我不確定這是否是編譯時常量(「stack」+「overflow」是),而且比通過JLS挖掘更容易。 – chrylis
這很好。我已經提出了你的答案。我添加了JLS參考作爲評論,所以如果有人願意的話。 – davmac
這個問題肯定是不可判定的,但你可以找到java編譯器的某些組合和JVM是如何做的。
據我所看到的,沒有什麼能阻止一個人寫一個Java編譯器,當它看到字符串常量,它,發出的字節代碼來創建在堆中的字符串以某種方式只要如規定的規則在JLS中關於字符串的字面依然保留。例如,String.intern
可以保持一個全球地圖,以及編譯器可以像如下編譯字符串文字:
create a char array of the desired size
put character at index 0
put character at index 1
...
put character at index (length-1)
construct the actual string object
pass the String just created to String.intern and leave result on the stack
其實,我們可以有一個預處理器改變所有的字符串常量,
(extra.HeapString.createString(new char[] { ... }))
和有createString
創建一個字符串實例的方式,以保持字符串文字的規則。而且你無法編寫一個能夠檢測它是從原始源還是從預處理源編譯的程序(除了通過在extra.HeapString
上的反思)。
你爲什麼反對他?這是一個字符串常量。 –
這個問題的「哪裏是字符串創建」和「哪裏是參數存儲」方面大多是單獨的答案。參數傳遞機制在字符串和其他對象上運行相同,但根據JVM,字符串文字可能會或可能不會以特殊方式分配。 – user2357112