这让我很震惊。
如果您有一个 Java Long 变量,并且您使用 == 运算符检查原始值是否相等,则该值的运行时类型将更改为原始 long。
随后检查变量的空值然后抛出意外的 NullPointerException。
所以在测试类中:
public class LongDebug {
public static void main(String[] args) {
Long validValue = 1L;
Long invalidValue = -1L;
Long nullValue = null;
System.out.println("\nTesting the valid value:");
testExpectedBehaviour(validValue);
testUnExpectedBehaviour(validValue);
System.out.println("\nTesting the invalid value:");
testExpectedBehaviour(invalidValue);
testUnExpectedBehaviour(invalidValue);
System.out.println("\nTesting the null value:");
testExpectedBehaviour(nullValue);
testUnExpectedBehaviour(nullValue);
}
/**
* @param validValue
*/
private static void testExpectedBehaviour(Long value) {
if (value == null || value == -1) System.out.println("Expected: The value was null or invalid");
else System.out.println("Expected: The value was valid");
}
private static void testUnExpectedBehaviour(Long value) {
try {
if (value == -1 || value == null) System.out.println("Unexpected: The value was null or invalid");
else System.out.println("Unexpected: The value was valid");
} catch (NullPointerException e) {
System.out.println("Unexpected: The system threw an unexpected NullPointerException");
}
}
}
我得到的结果是:
Testing the valid value:
Expected: The value was valid
Unexpected: The value was valid
Testing the invalid value:
Expected: The value was null or invalid
Unexpected: The value was null or invalid
Testing the null value:
Expected: The value was null or invalid
Unexpected: The system threw an unexpected NullPointerException
这是符合规范还是 JDK 中的错误?
最佳答案
问题是:
value == -1 || value == null
表达式从左到右求值,因为 Long
必须先拆箱,JVM 将其转换为:
value.longValue() == -1 || value == null
和value.longValue()
当 value
为 null
参数时抛出 NullPointerException
。它永远不会到达表达式的第二部分。
它在顺序不同时有效:
value == null || value == -1
因为如果 value
为 null
,第二部分(当 value
为 null
) 由于 boolean 表达式 short-circuit evaluation 从未被执行.
Is this on spec or a bug in the JDK?
当然这不是错误。原始值包装器的拆箱方式符合规范(5.1.8. Unboxing Conversion):
- If
r
is a reference of typeLong
, then unboxing conversion convertsr
intor.longValue()
应用拆箱后,剩下的就是标准的Java。
关于java - 相等检查后使用 Long 的 NullPointerException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12686718/