数字上不需要的自动装箱魔法

por*_*szd 8 java autoboxing

以下程序分别打印'false'和'true':

Number n = true ? new Long(1) : new Double(2.0);
System.out.println(n instanceof Long);
System.out.println(n instanceof Double);
Run Code Online (Sandbox Code Playgroud)

所以它不会是长而是双.但是,它按照正常类的方式工作:拥有

class B {}
class D1 extends B {}
class D2 extends B {}
Run Code Online (Sandbox Code Playgroud)

这将打印'true':

B b = true ? new D1() : new D2();
System.out.println(b instanceof D1);
Run Code Online (Sandbox Code Playgroud)

这意味着它不像上面的例子那样工作.

我确信有一些与自动装箱相关的东西,但它真的应该如何运作吗?为什么她使用装箱,当Number类是Long和Double的超类时,表达式可以被评估为Number?

这真的很痛苦,因为在打印n时,它会打印为双倍值.(我知道解决方法很容易,但让我发疯了)

nd.*_*nd. 7

让我们在这里取出语言律师的书:JLS§15.25

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

  • 如果第二个和第三个操作数具有相同的类型(可以是null类型),那么这就是条件表达式的类型.

长和双不是同一类型 - 不适用.

  • 如果第二个和第三个操作数之一是原始类型T,而另一个操作数的类型是将装箱转换(第5.1.7节)应用于T的结果,那么条件表达式的类型是T.

这两个值都不是原始的 - 不适用.

  • 如果第二个和第三个操作数之一是null类型而另一个操作数的类型是引用类型,则条件表达式的类型是该引用类型.

这两个值都不为null - 不适用.

  • 否则,如果第二个和第三个操作数具有可转换(第5.1.8节)到数字类型的类型,则有几种情况:
    • [...字节/短/字符的特殊情况及其盒装等价物......]
    • 否则,二进制数字提升(第5.6.2节)将应用于操作数类型,条件表达式的类型是第二个和第三个操作数的提升类型.

此规则在此处适用,这意味着条件运算符的结果类型就像两个值都是未装箱的一样.是假设背后的理由是,否则Number n = bool ? 1 : 2.0并Number n = bool ? new Long(1) : new Double(2.0)有不同的价值观.这种行为也是出乎意料的 - 更糟糕的是 - 不一致.