2016-01-20 93 views
5

我對這個程序的輸出有點迷惑:Java JLS是否指定原始包裝類型的提升?

public class xx { 
    public static void main(String[] args) throws Exception { 
     Number x = false ? new Long(123) : new Integer(456); 
     System.out.println(x + " isa " + x.getClass().getName()); 
    } 
} 

這裏就是它輸出:

456 isa java.lang.Long 

它出現的編譯器是「促進」 Integer類型的對象,以Long,就像它通常會促進原始價值。我從來沒有聽說過對象促銷,這種行爲似乎很令人驚訝。

我的問題:根據JLS,這真的是正確的行爲嗎?如果是這樣,我希望儘可能看到參考。

或者是這種某種自動裝箱已經消失的編譯器錯誤?

我使用:

java version "1.8.0_60" 
Java(TM) SE Runtime Environment (build 1.8.0_60-b27) 
Java HotSpot(TM) 64-Bit Server VM (build 25.60-b23, mixed mode) 

回答

4

這實際上是二進制數值提升JLS, Section 5.6.2)。

當操作者施加的二進制數值提升到一對操作數,其中的每一個必須表示一個值,該值可以轉換爲一個數字類型,適用下列規則,爲了:

  1. 如果任何操作數都是引用類型,它將經歷拆箱轉換(§5.1.8)。

  2. 加寬原語轉換(§5.1.2)被施加到轉換的任一個或由下面的規則中指定的兩個操作數:

    • 如果操作數的類型是雙,另一種是轉換爲double 。

    • 否則,如果任一操作數的類型爲float,則另一個操作數轉換爲float。

    • 否則,如果任一操作數的類型爲long,則另一個操作數轉換爲long。

    • 否則,兩個操作數都轉換爲int類型。

      ...

      • 在某些情況下,條件運算符:

二元數值提升是對某些運營商的操作數執行? (§15.25)

因此,操作數拆箱和456被擴大至456L

此外,LongInteger的具體情況由條件運算符的JLS部分明確覆蓋,JLS Section 15.25, Table 15.25-C

BNP(長,整數)

其中, 「BNP」 是指二進制數值提升。因此,條件運算符表達式的類型爲long,它被裝箱到Long以分配給Number

3

的JLS定義表達式a ? b : c的類型的情況下bc分別爲長和整數,在this table

表達式的類型確實是Long,並且確實存在Integer到Long的二進制數字提升(bnp)。

規則是進一步詳細here

類型數值條件表達式確定爲如下:

[...]

否則,二進制數值提升(§5.6 .2)應用於操作數類型,並且條件表達式的類型是第二個和第三個操作數的提升類型。