2012-11-17 67 views
4

我的java類最後絃樂VS最終整數

private static final String constantString = "Constant";  
private static final Integer constantInteger = 5; 
public static void main(String[] args) { 
    String s2 = constantString + "append"; // LINENUMBER 9 
    Integer i2 = constantInteger + 7; // LINENUMBER 10 
} 

字節碼

LINENUMBER 9 L0 
    LDC "Constantappend" 
    ASTORE 1 
    L1 
    LINENUMBER 10 L1 
    GETSTATIC TestClass.constantInteger : Ljava/lang/Integer; 
    INVOKEVIRTUAL java/lang/Integer.intValue()I 
    BIPUSH 7 
    IADD 

問題NO1:爲什麼編譯器不能用5替換最終整數(constantInteger)值,但字符串不是沒有!

如果除去最後關鍵字爲整數變量

Java代碼:

private static Integer constantInteger = 5; 

字節代碼:

LINENUMBER 10 L1 
GETSTATIC TestClass.constantInteger : Ljava/lang/Integer; 
INVOKEVIRTUAL java/lang/Integer.intValue()I 
BIPUSH 7 

字節代碼是在兩種不同的情況相同的(靜態最終整數,靜態整數)

問題2:那麼使Integer最終有什麼用?

+2

「那麼Integer最終的用途是什麼?」編譯器不會讓你改變它的值。 – leonbloy

回答

5

編譯器不會注意到,具有非空值的最終整數必然非空。所以它繼續前進並將其解開。 JIT編譯器完全有可能在通往機器代碼的路上改進它;這似乎不太可能,因爲這對於您的應用程序的性能來說是一個真正的問題。

'最終'是關於語義,而不是性能。語言保證了語義;表現完全是執行者的奇想。因此,明確回答'問題#2':最後的要點是要有防止修改的語義。還要注意嵌入式匿名類的規則,他們可能只使用最終的局部變量。

3

答案很簡單:儘量static final int constantInteger = 5

編譯器只能更換常量表達式。 Java有所謂的原始值,即以小寫字符(long,int,char,...)開頭的類型。這些值不是對象,因此它們不能有狀態並可以直接替換。

作爲優化字符串對象也可以被編譯器視爲常量。在運行時,String只是一個容納字符數組的容器,但在編譯時,編譯器假定String只是字符數據。然而,String是唯一的例外。

由於類似的原因,您可以使用StringClass,但註釋中的值沒有其他對象類型。

6

猜測:原因是字符串實習。編譯器實施字符串並對interned字符串進行優化。但它並沒有實習Numbers,而顯然缺乏優化。

我想不出有什麼理由不能優化Integer大小寫,除非它只是在編譯器中沒有實現。正如其他答案中所提到的,Integer +涉及裝箱/拆箱操作,與字符串+及其隱含的StringBuilder優化和實習邏輯完全不同。因此,如果查看,String +優化可能來自編譯器實現點的「免費」。

1

Java Language Specification, v3

字符串由常量表達式(§15.28)來計算在 編譯時計算,並然後處理過的,好像他們是文字。

您的字符串表達式由兩個文字組成,在編譯時計算爲單個文字。整數沒有得到這樣的待遇。