5

我最近尝试运行以下两个代码片段,并对输出感到惊讶。

第一的:

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

第二:

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

第一个示例产生以下输出:
true

第二个示例产生以下输出:    com.blah.main(SanityCheck.java:26)
线程“main”java.lang.NullPointerException中的异常

我原以为这两个示例都应该导致空指针异常,因为任何短路都是从左到右应用的。从布尔值拆箱的尝试应该在逻辑的另一端之前失败或被考虑。

谁能解释这种不一致的行为?

4

3 回答 3

4

我通过 JAD 运行类文件,看看优化后的代码是什么样子的。对于真实情况:

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

对于虚假情况:

// ...
System.out.println(null.booleanValue());
// ...
于 2013-08-23T03:46:07.027 回答
2

我会试一试。当编译器试图解释这两个语句时,主要区别在于右侧为 true 的语句不需要使用左手布尔值进行计算,而右侧为 false 的语句则需要。

布尔值是一个对象,因此它可以设置为空。那不是引发异常的地方。当您尝试对设置为 null 的布尔对象执行操作时,将引发 NullPointerException。在 true 的情况下,编译器会将转换 null 传递给布尔值,并且因为与 true 的 OR'ing 将始终产生 true,所以条件为 true。在 false 的情况下,编译器将再次将强制转换 null 传递给布尔值,然后它会检查 false,如果条件为 false,它需要与布尔值计算 OR,因为条件最终可能是 true 或 false。当计算发生时,会抛出 NullPointerException。

于 2013-08-23T03:12:07.770 回答
1

我无法重现您的结果。我实际上在这两种情况下都得到了 NPE。

根据 JLS,总是首先计算左侧操作数表达式。评估时(Boolean)null,将对空布尔对象执行自动拆箱。特别是,底层代码null.booleanValue()导致了 NPE。

于 2013-08-23T04:04:09.197 回答