【问题标题】:How can this Java code compile without error?这段Java代码如何编译没有错误?
【发布时间】:2017-03-28 15:01:36
【问题描述】:

谁能解释为什么这段 Java 代码可以编译?

public class Main {
     public static void main(String []args){
        System.out.println(foo(true));
        System.out.println(foo(false));
     }

     public static boolean foo(boolean value) {
         // this should make the compiler say something, at least complain a bit...
         return value ? true : null;
     }
}

【问题讨论】:

  • 自动装箱.....
  • 您浏览过 JLS 吗?你认为它违反了哪条规则?这看起来像是被docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.25覆盖了
  • @OliverCharlesworth 但是为什么当顺序颠倒时它不能编译?
  • @milin - 但它确实可以编译:/
  • @JonSkeet 当第二个操作数为“布尔”且第三个为“null”时,我无法找到任何规则,但我不确定是否构成“没有规则被破坏”,而是我有一种被忽视的感觉......

标签: java compiler-errors compilation javac


【解决方案1】:

正如 Oliver 在 cmets 中所说,这个编译的原因是自动装箱。

null 可以自动装箱为BooleanBoolean 可以自动拆箱为boolean,使编译器满意。在运行时自动装箱有效,但是当它被拆箱到 boolean 时,它会抛出 NullPointerException

【讨论】:

  • 但是为什么倒序时编译不出来呢?
  • 哪个排序?
  • 正如上面提到的 OliverCharlesworth,我错了——它确实可以编译!
  • 唷。我不想开始挖掘一些关于三元运算符自动装箱或其他东西的晦涩规则:)
  • 感谢您的努力! :) 我现在明白整个表达式的返回类型是从操作数派生的,然后根据应该保存评估表达式的类型进行验证。我只是无法摆脱这应该失败的感觉,但我明白为什么它不会......
【解决方案2】:

我们有什么样的条件表达式(JLS 15.25)?

  • 显然不是数字条件表达式。
  • 布尔条件表达式需要两个boolean 类型的操作数,这与第三个操作数null 相违背
  • 所以我们有一个reference conditional expression

对于参考条件表达式表15.25-E 指定布尔值(第二个)和空值(第三个)的组合确定完整表达式的类型为lub(Boolean,null)

对于运行时评估,这句话提供了所需的清晰度:

在运行时,首先计算条件表达式的第一个操作数表达式。如有必要,对结果执行拆箱转换。

根据第一个操作数,会发生以下情况:

  • true 自动装箱为 Boolean
  • 采用null,它已经与Boolean 兼容(基于JLS-4.1)(这不是其他答案所声称的自动装箱

生成的Boolean 将被自动拆箱,在第二种情况下将抛出NullPointerException

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多