Java JLS是否指定了原始包装类型的提升?

时间:2016-01-20 22:36:25

标签: 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

似乎编译器是"促进"类型IntegerLong的对象,就像通常会提升原始值一样。我从未听说过对象推广,这种行为似乎非常令人惊讶。

我的问题:根据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)

2 个答案:

答案 0 :(得分:4)

这实际上是二进制数字促销JLS, Section 5.6.2)。

  

当运算符将二进制数字提升应用于一对操作数时,每个操作数必须表示可转换为数字类型的值,以下规则适用:

     
      
  1. 如果任何操作数属于引用类型,则进行拆箱转换(第5.1.8节)。

  2.   
  3. 应用扩展基元转换(第5.1.2节)来转换由以下规则指定的一个或两个操作数:

         
        
    • 如果任一操作数的类型为double,则另一个操作数转换为double。

    •   
    • 否则,如果任一操作数的类型为float,则另一个操作数转换为float。

    •   
    • 否则,如果任一操作数的类型为long,则另一个操作数转换为long。

    •   
    • 否则,两个操作数都将转换为int类型。

    •   
  4.         

    对某些运算符的操作数执行二进制数字提升:

         

    ...

         
        
    • 在某些情况下,条件运算符? :(§15.25)
    •   

因此,操作数已取消装箱,456扩展为456L

此外,条件运算符JLS Section 15.25, Table 15.25-C的JLS部分明确涵盖了LongInteger的具体情况。

  

BNP(长,整数)

其中“bnp”表示二进制数字促销。因此,条件运算符表达式的类型为long,它将被装箱到Long以分配给Number

答案 1 :(得分:3)

this table中,JLS分别定义a ? b : cb分别为Long和Integer的表达式c的类型。

表达式的类型确实是Long,并且确实存在Integer到Long的二进制数字提升(bnp)。

该规则进一步详细here

  

数字条件表达式的类型确定如下:

     

[...]

     

否则,二进制数字提升(第5.6.2节)将应用于操作数类型,条件表达式的类型是第二个和第三个操作数的提升类型。