儘管日誌記錄級別設置爲INFO,並且在運行時該條件永遠不會得到滿足,但如果「Hi
」不會被初始化,我如何能夠以編程方式進行驗證?如何以編程方式驗證字符串是否已初始化?
if(log.isDebug()){
log.debug("Hi");
}
我的意思是,因爲日誌記錄級別爲INFO,該記錄將不會有機會來打印消息「嗨」,我關心的是,我怎麼能當JRE或JDK會發現/即使條件不滿足也不會採取措施來準備「Hi」。
儘管日誌記錄級別設置爲INFO,並且在運行時該條件永遠不會得到滿足,但如果「Hi
」不會被初始化,我如何能夠以編程方式進行驗證?如何以編程方式驗證字符串是否已初始化?
if(log.isDebug()){
log.debug("Hi");
}
我的意思是,因爲日誌記錄級別爲INFO,該記錄將不會有機會來打印消息「嗨」,我關心的是,我怎麼能當JRE或JDK會發現/即使條件不滿足也不會採取措施來準備「Hi」。
轉儲的字節碼。 String常量將會有一個「ldc」操作碼。操作碼第一次被執行時,實際的字符串將被創建。然後,字符串將被緩存在常量池中,以供後續調用/迭代重用。如果「ldc」從不執行,則不會創建字符串。
嗨熱舔,我讀了你的其他意見,你可以請擴大你提到的部分「實際上,字符串值通常不會被創建,除非被引用。在字節碼中會有一個「load constant」操作碼,並且第一次執行該常量將從常量池中提取並創建一個String對象。 「 – 2012-01-27 03:01:27
每個類都有一個常量池,其中一部分是從.class文件中取得的一個不變的結構,但是一部分是一個可以動態更新的表。當引用一個常量字符串時,該表被檢查(即is指針null?)來查看該常量是否已經創建,如果不是,則將不變結構中的UTF8值擴展爲UTF16,並用於創建(和實體)String,然後將該String的指針存儲在表中。 (至少這是它在規範JVM中的工作方式,如果沒有對該類進行任何特殊處理。) – 2012-01-27 12:35:36
這段代碼沒有什麼需要「初始化」的;字符串文字「Hi」將被編譯器放置到您的.class
文件中,因此無論是否實際使用,它都可以在運行時使用。
實際上,除非被引用,否則通常不會創建字符串值。在字節碼中會有一個「load constant」操作碼,並且第一次執行該常量將從常量池中提取並創建一個String對象。 – 2012-01-27 02:51:25
所以字符串將會出現在字節碼中,但是如果它的值在運行時從不使用,則不會加載到內存中。我想你可以稱之爲「未初始化」。 – Wyzard 2012-01-27 02:57:52
字符串「嗨」是類定義的一部分。除非編譯器可以確定if
的主體是死代碼並且不需要文字,那麼當類加載器加載該類時,它將加載文字值。由於它是一個編譯時常量,它也會自動實現。
編譯器無法知道將類加載到某個未知執行環境時,log.isDebug()
的行爲。衆所周知,記錄器類的定義可能會更改,以便isDebug()
返回true
,而不管爲記錄級別設置的值如何。
我認爲字符串字面的「喜」是堆內存初始化只讀
你可以做這樣的方法和計算內存三角洲:
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();
}
所有字符串都是「只讀」的,因爲它們是不可變的。 「Hi」沒有什麼特別之處,一旦創建,除了常量池中的字符串總是被實現的,而實習則需要用戶爲用戶創建的字符串執行操作。 – 2012-01-27 02:58:08
字符串文字「嗨」 – 2012-01-27 02:33:59
你的意思是's == null'嗎? – 2012-01-27 02:34:22
不清楚,請編輯 – 2012-01-27 02:36:39