2013-08-07 37 views
10

對於程序中的以下語句,將在堆內存和字符串常量池中創建多少個對象?Java和內存管理中的對象生命週期?

我需要清晰的對象創建。我讀過的許多資料都沒有詳細說明。當對象被破壞時,我很困惑。

String a="MAM"+"BCD"+"EFG"+"GFE"; 

將創建多少個對象?

我正在尋找有關對象,方法和類的生命週期的良好材料,以及JVM在動態更改和修改時如何處理它們。

+0

您怎麼看? –

+0

有人應該在其上運行'javah'。我敢打賭它只會顯示一個常數。 – Rekin

+0

upto我只有一個,但很多朋友在這個討論困惑我 [鏈接](https://www.facebook.com/groups/java.for.developers/10151748401034501/?notif_t=group_comment_reply) – saikiran

回答

3

只有一個對象被創建並放置在常量池中,除非它已經存在,在這種情況下使用現有對象。編譯器將字符串常量連接在一起,如JLS 3.10.5和15.28中所指定。

長字符串文字總是可以被分成較短的段,並使用字符串連接運算符寫成(可能括號內)的表達+

http://docs.oracle.com/javase/specs/jls/se7/html/jls-3.html#jls-3.10.5

6

只創建一個對象。

string s1 = "java"; 
string s2 = "ja" + "va"; 
s.o.p(s1==s2); 

該聲明爲真。

String s1="java"; 
string s2 = "ja"; 
String s3 = s2 +"va"; 
s.o.p(s1==s3); 

該聲明產生錯誤。因此,最小的一個顯然應該是永久的,然後'+'操作符使用new()在非常量池中生成新的字符串對象。 所以,你問的問題沒有一個也是永久性的。這意味着它只創建一個對象。

20

"MAM"+"BCD"+"EFG"+"GFE"是編譯時常量表達式並將其編譯爲"MAMBCDEFGGFE"字符串文字。當加載包含上述代碼的類時,JVM將從該文字創建一個String的實例,並將此String放入字符串池中。因此String a = "MAM"+"BCD"+"EFG"+"GFE";不創建任何對象,請參閱JLS 15.18.1. String Concatenation Operator +

String對象是新創建(§12.5),除非表達是一個編譯時間常量表達式(§15.28)。

它只是將對池中String對象的引用分配給本地變量a

+0

我現在得到了這個概念謝謝@Evgeniy – saikiran

2

由於String a會編譯成"MAMBCDEFGGFE",因此只會創建一個對象。

0

在您的示例中指出單個堆對象的答案是正確的。但是,請考慮以下代碼:

public class Tester 
{ 
    public String a="MAM"; 
    public String b ="BCD"; 
    public String c = "EFG"; 
    public String d ="GFE"; 

    public Tester() 
    { 
     String abcd = a + b + c + d; 
    } 
} 

在此示例中,創建了7個字符串。 a,b,c和d不會被編譯成一個常量 - 它們是成員。然後爲每個+運算符創建1個字符串 - 從語義上講,+是一個串聯,但從邏輯上說,它正在內存中創建一個新字符串。前2個運算符字符串會立即丟棄,現在可以進行垃圾回收了,但內存流失仍然存在。

技術上存在於第8個對象中。 Tester的實例。

編輯:這已經被證明是無稽之談在評論

+3

javac編譯器有一個優化:不是每個'+'都生成一個新的字符串。創建一個內部的'StringBuilder',附加'a','b','c','c',然後創建一個'String'。這種優化已經存在了十多年。所以計算結果是5個String和5個關聯的char [],1個StringBuilder以及至少一個關聯的char [] - 最終由於動態調整大小。 –

+0

我站好了! +1 – Gusdor

+0

你的意思是它會首先追加一個+ b,然後把一個+ b看作一個字符串並追加到c?我沒有得到你 – saikiran

3

大多數的答案似乎把重點在於:a)完整的表達是一個編譯時間常數和b)該行本身並不構建一個新的對象,但只有一個參考一個對象。

但是迄今爲止沒有人提到過,String本身包含對內部char[](它也在常量池中)的引用。

摘要:常量池中有兩個對象(Stringchar[])。該行既不創建也不銷燬任何對象。

以及有關:

我很困惑,當對象被銷燬。

沒有對象被銷燬,因爲常量池中的東西只會在類本身被卸載時被銷燬。最多可以說,參考文獻a最終會超出範圍。