2014-02-10 79 views
0

做實際參數。如果我通過String字面一些metohd爲:凡在Java軟件商店

String s=new String("stack"); 
String s2=s.concat("overflow"); 

將在其中存儲字符串「溢出」。

我的一個朋友爭辯說,它創建在String不斷池,我反對他。

請讓我知道

在此先感謝。

+2

你爲什麼反對他?這是一個字符串常量。 –

+2

這個問題的「哪裏是字符串創建」和「哪裏是參數存儲」方面大多是單獨的答案。參數傳遞機制在字符串和其他對象上運行相同,但根據JVM,字符串文字可能會或可能不會以特殊方式分配。 – user2357112

回答

3

全部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; 
+1

JLS的相關部分:http://docs.oracle.com/javase/specs/jls/se7/html/jls-3.html#jls-3.10.5 - 「此外,字符串常常指向相同的這是因爲字符串文字 - 或者更一般地說,是常量表達式(§15.28)值的字符串 - 被「interned」,以便使用方法String.intern共享唯一實例。 – davmac

+0

@davmac我實際上編譯了這段代碼,因爲我不確定這是否是編譯時常量(「stack」+「overflow」是),而且比通過JLS挖掘更容易。 – chrylis

+0

這很好。我已經提出了你的答案。我添加了JLS參考作爲評論,所以如果有人願意的話。 – davmac

0

這個問題肯定是不可判定的,但你可以找到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上的反思)。

+0

反對的字符串池和堆有誤導性:字符串池可能存儲在主堆中(例如自Java 7以來就是熱點的情況)。 – assylias

+1

此行爲在JLS中明確指定。你可以編寫一個以各種方式打破規則的編譯器,但它不會是一個正確的Java編譯器。 – chrylis

+1

@chrylis這就是我的意思。 – assylias

-1

字符串stack將在堆中,字符串overflow在常量池中,第三個字符串作爲常量池中的串聯結果stackoverflow

+0

大部分錯誤,對,錯。 'stack'在常量池中,'overflow'在常量池中,'stackoverflow'在堆中。根據JVM作者的判斷,常量池可能在堆上。除非明確實行,否則「stackoverflow」不會進入池中。 – chrylis

+2

「堆棧」的文字將在常量池中,但s將引用它將在堆上的副本(由於新的String(...)')。 – davmac