我创建了一个equals方法。我相信我可以用两种方式做到这一点,但java似乎并不同意。这是我知道的第一个例子。
public class HelloWorld {
public boolean equals(Object rhs){
if(this==rhs){
return true;
}else if( rhs==null || this.getClass() != rhs.getClass()){
return false;
}else{
HelloWorld tmp =(HelloWorld)rhs;
return true;
}
}
public static void main(String[] args){
HelloWorld c = new HelloWorld();
System.out.println(c.equals(null));
}
}
这是第二个不起作用的例子。
是一个nullpointerexception而不是返回false public class HelloWorld {
public boolean equals(Object rhs){
if(this==rhs){
return true;
}else if(this.getClass() != rhs.getClass() || rhs==null){
return false;
}else{
HelloWorld tmp =(HelloWorld)rhs;
return true;
}
}
public static void main(String[] args){
HelloWorld c = new HelloWorld();
System.out.println(c.equals(null));
}
}
我的问题......两段代码之间的唯一区别在于我写的第一篇文章
rhs ==null ||...
在第二部分中,它位于OR运算符的另一侧,所以
...|| rhs==null
为什么第一种情况不会给我一个Nullpointer,但第二种情况呢?为什么在OR运算符的哪一边写入布尔语句是否重要?
答案 0 :(得分:6)
这很重要,因为作为条件“OR”运算符的||
如果左表达式为true
,则不会评估正确的表达式,因为结果已经可以确定。这被称为“短路”行为。
Section 15.24 of the JLS涵盖了这一点:
条件或运算符||运算符就像| (§15.22.2),但仅在其左侧操作数的值为假时才计算其右侧操作数。
未评估右手表达式,因此避免使用NullPointerException
。
(&&
条件“AND”运算符,也是“短路”,如果左侧为true
,则仅评估右侧。)
答案 1 :(得分:2)
如果左侧按JLS section 15.24评估为||
,则true
运算符的右侧不会执行:
条件或运算符
||
运算符类似于|
(第15.22.2节),但仅当其左侧操作数的值为{{1}时才计算其右侧操作数}。
因此,在第一种情况下,false
的计算结果为true,因此rhs == null
未执行 - 否则将抛出rhs.getClass()
。
在第二种情况下,您无条件地执行NullPointerException
,因此例外。
如果您使用rhs.getClass()
代替|
,则会在两种情况下都获得例外。
答案 2 :(得分:1)
我建议您遵循Joshua Bloch的方法,从他的" Effective Java"中正确实施equals方法。第3章。
如果你实现了equals,你也应该实现hashCode。
答案 3 :(得分:0)
正在使用' ||'这是条件OR与短路行为,如果第一个条件成立,则第二个条件未被评估。
例如,如果您正在使用(A || B)---如果A为真,则不会评估B.
这就是为什么在rhs为空的情况下你得到空指针异常的原因。
第一组代码实际上是正确的,因为你正确处理那里的空案例,这与第二集的情况不同。
如果您希望评估这两个条件并且不希望出现短路行为,则可以使用' |'运算符而不是' ||'。
因此,在(A | B)的情况下---即使A为真,也会评估B.