简体   繁体   English

拆箱如何在短路布尔表达式中工作?

[英]How does unboxing work in short-circuited boolean expressions?

I recently tried to run the following two snippets of code and was surprised at the output. 我最近尝试运行以下两段代码,并对输出感到惊讶。

First: 第一:

// ...
System.out.println( (Boolean)null || true );
// ...

Second: 第二:

// ...
System.out.println( (Boolean)null || false );
// ...

The first example results in the following output: 第一个示例导致以下输出:
true 真正

The second example results in the following output: 第二个示例导致以下输出:
Exception in thread "main" java.lang.NullPointerException 线程“main”java.lang.NullPointerException中的异常
at com.blah.main(SanityCheck.java:26) 在com.blah.main(SanityCheck.java:26)

I would have thought both examples should result in a null pointer exception, as any short-circuiting is applied left-to-right. 我原以为这两个例子都会导致空指针异常,因为任何短路都是从左到右应用的。 The attempt to unbox the boolean from the Boolean should have failed before the other side of the logical or was given consideration. 从布尔值中取消装箱布尔值的尝试应该在逻辑的另一侧或考虑之前失败。

Can anyone explain this inconsistent behaviour? 谁能解释这种不一致的行为?

I ran the class file through JAD to see what the optimised code looked like. 我通过JAD运行类文件,看看优化代码的样子。 For the true case: 对于真实案例:

// ...
System.out.println(true);
// ...

For the false case: 对于虚假案件:

// ...
System.out.println(null.booleanValue());
// ...

I'll take a jab at it. 我会抨击它。 As the compiler attempts to interpret the two statements, the main difference is that the statement with true on the right side is not required to make a computation with the left handed Boolean, while the statement with false on the right side is. 当编译器试图解释这两个语句时,主要区别在于右侧的true语句不需要用左手布尔值进行计算,而右侧的语句是false。

A Boolean is an Object, thus it can be set to null. 布尔值是一个Object,因此可以设置为null。 That is not where the exception is thrown. 这不是引发异常的地方。 The NullPointerException is thrown when you attempt to execute an operation on a Boolean object that is set to null. 当您尝试对设置为null的Boolean对象执行操作时,将引发NullPointerException。 In the true case, the compiler will pass casting null to a Boolean, and because OR'ing with true will always yield true, the conditional is true. 在真实情况下,编译器会将cast null传递给布尔值,并且因为OR与true将始终产生true,条件为true。 In the false case, the compiler will pass casting null to a Boolean again, it will then check false, and if the condition is false, it needs to compute the OR with the Boolean because the condition could ultimately come out as true or false. 在false的情况下,编译器会再次将cast null传递给Boolean,然后检查false,如果条件为false,则需要使用Boolean计算OR,因为条件最终可能为true或false。 When the computation happens, the NullPointerException is thrown. 计算发生时,抛出NullPointerException。

I cannot reproduce your results. 我无法重现你的结果。 I actually get NPE for both cases. 我实际上得到两个案件的NPE。

As per JLS, the left-hand operand expression is always evaluated first. 根据JLS,始终首先评估左侧操作数表达式。 When (Boolean)null is evaluated, an auto unboxing is performed on a null Boolean object. 当计算(Boolean)null ,将对null Boolean对象执行自动取消装箱。 In particular, the underlying code null.booleanValue() is causing the NPE. 特别是,底层代码null.booleanValue()正在导致NPE。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM