简短的回答
关键点是这样的:
==
两个引用类型之间总是引用比较
- 通常情况下,例如使用
Integer
and String
,您会想要equals
使用
==
引用类型和数字原始类型之间始终是数字比较
- 引用类型将进行拆箱转换
- 拆箱
null
总是抛出NullPointerException
- 虽然 Java 对 有许多特殊处理
String
,但它实际上不是原始类型
上述语句适用于任何给定的有效Java 代码。有了这种理解,您提供的代码段中就没有任何不一致之处。
长答案
以下是相关的 JLS 部分:
如果相等运算符的操作数既是引用类型又是null类型,则该操作是对象相等。
这解释了以下内容:
Integer i = null;
String str = null;
if (i == null) { // Nothing happens
}
if (str == null) { // Nothing happens
}
if (str == "0") { // Nothing happens
}
两个操作数都是引用类型,这==
就是引用相等比较的原因。
这也解释了以下内容:
System.out.println(new Integer(0) == new Integer(0)); // "false"
System.out.println("X" == "x".toUpperCase()); // "false"
要==
实现数值相等,至少有一个操作数必须是数值类型:
如果相等运算符的操作数都是数字类型,或者一个是数字类型而另一个可以转换为数字类型,则对操作数执行二进制数字提升。如果操作数的提升类型是int
or long
,则执行整数相等测试;如果提升的类型是float or
double`,则执行浮点相等测试。
请注意,二进制数字提升执行值集转换和拆箱转换。
这说明:
Integer i = null;
if (i == 0) { //NullPointerException
}
这是Effective Java 2nd Edition,Item 49: Prefer primitives to boxed primitives的摘录:
总之,只要您有选择,就优先使用原语而不是盒装原语。原始类型更简单、更快。如果您必须使用盒装图元,请小心!自动装箱减少了使用装箱原语的冗长,但不会降低危险。当您的程序将两个装箱原语与==
运算符进行比较时,它会进行身份比较,这几乎肯定不是您想要的。当您的程序进行涉及装箱和拆箱原语的混合类型计算时,它会拆箱,而当您的程序拆箱时,它可以抛出NullPointerException
. 最后,当您的程序将原始值装箱时,可能会导致成本高昂且不必要的对象创建。
有些地方你别无选择,只能使用盒装原语,例如泛型,但否则你应该认真考虑使用盒装原语的决定是否合理。
参考
相关问题
相关问题