2012-01-27 41 views
0

儘管日誌記錄級別設置爲INFO,並且在運行時該條件永遠不會得到滿足,但如果「Hi」不會被初始化,我如何能夠以編程方式進行驗證?如何以編程方式驗證字符串是否已初始化?

if(log.isDebug()){ 
    log.debug("Hi"); 
} 

我的意思是,因爲日誌記錄級別爲INFO,該記錄將不會有機會來打印消息「嗨」,我關心的是,我怎麼能當JRE或JDK會發現/即使條件不滿足也不會採取措施來準備「Hi」。

+0

字符串文字「嗨」 – 2012-01-27 02:33:59

+0

你的意思是's == null'嗎? – 2012-01-27 02:34:22

+0

不清楚,請編輯 – 2012-01-27 02:36:39

回答

4

轉儲的字節碼。 String常量將會有一個「ldc」操作碼。操作碼第一次被執行時,實際的字符串將被創建。然後,字符串將被緩存在常量池中,以供後續調用/迭代重用。如果「ldc」從不執行,則不會創建字符串。

+0

嗨熱舔,我讀了你的其他意見,你可以請擴大你提到的部分「實際上,字符串值通常不會被創建,除非被引用。在字節碼中會有一個「load constant」操作碼,並且第一次執行該常量將從常量池中提取並創建一個String對象。 「 – 2012-01-27 03:01:27

+0

每個類都有一個常量池,其中一部分是從.class文件中取得的一個不變的結構,但是一部分是一個可以動態更新的表。當引用一個常量字符串時,該表被檢查(即is指針null?)來查看該常量是否已經創建,如果不是,則將不變結構中的UTF8值擴展爲UTF16,並用於創建(和實體)String,然後將該String的指針存儲在表中。 (至少這是它在規範JVM中的工作方式,如果沒有對該類進行任何特殊處理。) – 2012-01-27 12:35:36

0

這段代碼沒有什麼需要「初始化」的;字符串文字「Hi」將被編譯器放置到您的.class文件中,因此無論是否實際使用,它都可以在運行時使用。

+1

實際上,除非被引用,否則通常不會創建字符串值。在字節碼中會有一個「load constant」操作碼,並且第一次執行該常量將從常量池中提取並創建一個String對象。 – 2012-01-27 02:51:25

+0

所以字符串將會出現在字節碼中,但是如果它的值在運行時從不使用,則不會加載到內存中。我想你可以稱之爲「未初始化」。 – Wyzard 2012-01-27 02:57:52

3

字符串「嗨」是類定義的一部分。除非編譯器可以確定if的主體是死代碼並且不需要文字,那麼當類加載器加載該類時,它將加載文字值。由於它是一個編譯時常量,它也會自動實現。

編譯器無法知道將類加載到某個未知執行環境時,log.isDebug()的行爲。衆所周知,記錄器類的定義可能會更改,以便isDebug()返回true,而不管爲記錄級別設置的值如何。

0

我認爲字符串字面的「喜」是堆內存初始化只讀

你可以做這樣的方法和計算內存三角洲:

if(log.isDebug()){ 
    log.debug("literal"); 

    log.debug(memoryUsed()); 
     log.debug("Hi"); 
    log.debug(memoryUsed()); 

    log.debug("initialising"); 

    log.debug(memoryUsed()); 
    string x = "Hi" 
    log.debug(x); 
    log.debug(memoryUsed()); 
    } 


    static long memoryUsed() 
     { 
     return runtime.totalMemory() - runtime.freeMemory(); 
     } 
+0

所有字符串都是「只讀」的,因爲它們是不可變的。 「Hi」沒有什麼特別之處,一旦創建,除了常量池中的字符串總是被實現的,而實習則需要用戶爲用戶創建的字符串執行操作。 – 2012-01-27 02:58:08