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

Arc*_*hie 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());
    }
}
Run Code Online (Sandbox Code Playgroud)

这是它输出的内容:

456 isa java.lang.Long
Run Code Online (Sandbox Code Playgroud)

它出现在编译器"促进"类型的对象IntegerLong,就像它通常会促进原始值.我从来没有听说过对象推广,这种行为似乎非常令人惊讶.

我的问题:根据JLS,这是非常正确的行为吗?如果是这样,我希望尽可能看到参考.

或者这是一种autoboxing-gone-wild编译器错误?

我正在使用:

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)
Run Code Online (Sandbox Code Playgroud)

rge*_*man 4

这实际上是二进制数字提升JLS,第 5.6.2 节)。

\n\n
\n

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

\n\n
    \n
  1. 如果任何操作数是引用类型,则对其进行拆箱转换(\xc2\xa75.1.8)。

  2. \n
  3. 加宽基元转换 (\xc2\xa75.1.2) 用于按照以下规则指定转换一个或两个操作数:

    \n\n
      \n
    • 如果其中一个操作数的类型为 double,则另一个操作数将转换为 double。

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

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

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

    • \n
  4. \n
\n\n

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

\n\n

...

\n\n
    \n
  • 在某些情况下,条件运算符 ? :(\xc2\xa715.25)
  • \n
\n
\n\n

因此,操作数被拆箱并且456被扩展为456L

\n\n

此外,条件运算符的 JLS 部分(JLS 第 15.25 节,表 15.25-C)Long明确涵盖了和的具体情况。Integer

\n\n
\n

bnp(长整型)

\n
\n\n

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

\n