[英]Time of Strings Creation in Java
我正在為J2ME設備編寫一個應用程序,並且非常關心不必要的字符串創建。 由於使用Strings是內置的,即沒有必要明確地創建它們,我不確定我是否理解它。
例如,返回一個String(只是使用雙引號)在返回時創建字符串,即如果我有幾個返回語句返回不同的字符串,則只會創建一個字符串。 是對的嗎?
此外,當使用字符串打印帶有異常的消息時,如果不拋出異常,這些字符串永遠不會被創建,對吧?
抱歉打擾你這樣一個新手問題。
到目前為止,我對你收到的答案一點也不確定。 如果你只是返回一個字符串文字,例如
return "foo";
然后將這些值嵌入到類文件中。 JVM確保只創建該字符串的一個實例(來自文字) - 但我不認為在加載類本身時,它不會保證它不會為類中的所有常量創建字符串。
然后再次,因為字符串只會被創建一次 (每個字符串常量),這不太可能是一個問題。
現在,如果您的代碼實際上更像是這樣:
return "foo" + new Date();
那就是動態創建一個字符串 - 但只有在實際命中了return語句時才會創建它。
答案比其他一些答案建議的要復雜一些。
在加載類時,將創建一次與源代碼中的字符串文字對應的String值。 此外, 這些字符串會自動“實現”,這意味着如果相同的字面值出現在任何類的多個位置,則只保留一個字符串副本。 (任何其他副本, 如果它們被創建將收集垃圾。)
當應用程序調用new String(...)
,當它計算字符串連接表達式(即+
運算符)時,或者當它調用在引擎蓋下創建字符串的許多庫方法之一時,將創建一個新的String。
那么回答你的問題:
1 - 以下內容實際上根本不會創建一個String。 而是它將返回在加載類時創建的String:
return "some string";
2 - 以下將創建兩個字符串。 首先它將調用someObject.toString(),然后它將與文字連接,以給出另一個String。
return "The answer is :" + someObject;
3 - 以下內容不會創建字符串; 見1。
throw new Exception("Some message");
4 - 以下將在執行時創建兩個字符串; 見2。
throw new Exception(someObject + "is wrong");
(實際上,3和4掩蓋了這樣一個事實,即創建異常會導致捕獲當前線程的調用堆棧的詳細信息,並且這些細節包括每個幀的方法名稱,類名和文件名。字符串時未指定表示這些東西實際上是創建的,或者它們是否被實現。因此,創建Exception對象的行為可能會觸發創建多個字符串。)
是。
如果通過調用構造函數創建實例的表達式或不執行(對於字符串)評估文字的表達式,則不會創建任何內容。
而且,編譯器會進行一些優化。
基於字符串文字的字符串對象將只創建一次並在之后實現。
像這兒:
public String getHello() { return "Hello"; } public void test() { String s = getHello(); // String object created String t = getHello(); // no new String object created }
JVMS有不同的“意見”:
在以下情況下可能會隱式創建新的類實例:
- 加載包含String文字的類或接口可能會創建一個新的String對象(第2.4.8節)來表示該文字。 如果已經創建了一個String對象來表示該文字的上一個匹配項,或者如果已在表示與該文字相同的字符串的String對象上調用了String.intern方法,則可能不會發生這種情況。
所以上面的例子是不正確的(我每天都在學習新東西)。 VM在類加載期間檢查是否必須創建"Hello"
(如果尚未存在,則將創建String實例)。
所以現在我的理解是,VM為每個唯一的String文字創建一個String實例(在字節代碼級別上!),無論它是否被使用。
( 在字節代碼級別上,因為編譯器可以優化字符串文字與一個文字的連接,如:表達式"one"+"two"
將被編譯為"onetwo"
)
只有在調用時才會創建字符串(和其他對象)。
那么回答你的問題:
這里的主要概念是,在您的邏輯流使解釋器執行該行編譯代碼之前,任何String的堆分配(您所說的創建)或任何對象的更一般術語都不會發生。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.