[改善Java代码]equals应该考虑null值的情景

时间:2023-03-09 15:57:52
[改善Java代码]equals应该考虑null值的情景

建议46: equals应该考虑null值情景

继续上一建议的问题,我们解决了覆写equals的自反性问题,是不是就很完美了呢?再把main方法重构一下:

 public class Client {
public static void main(String[] args) {
Person p1 = new Person("张三");
Person p2 = new Person(null); List<Person> l =new ArrayList<Person>();
l.add(p1);
l.add(p2);
System.out.println("列表中是否包含张三:"+l.contains(p1));
System.out.println("列表中是否包含张三 :"+l.contains(p2));
}
} class Person{
private String name; public Person(String _name){
name = _name;
} @Override
public boolean equals(Object obj) {
if(obj instanceof Person){
Person p = (Person) obj;
return name.equalsIgnoreCase(p.getName().trim());
}
return false;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
}
}

很小的改动,那运行结果是什么呢?是两个true吗?我们来看运行结果:

列表中是否包含张三:true
Exception in thread "main" java.lang.NullPointerException

竟然抛异常了!为什么p1就能在List中检查一遍,并且执行p1.equals方法,而到了p2就开始报错了呢?仔细分析一下程序,马上明白了:当执行到p2.equals(p1)时,由于p2的name是一个null值,所以调用name. equalsIgnoreCase方法时就会报空指针异常了!出现这种情形是因为覆写equals没有遵循对称性原则:对于任何引用x和y的情形,如果x.equals(y)返回true,那么y.equals(x)也应该返回true。

问题知道了,解决也很简单,增加name是否为空进行判断即可,修改后的equals代码如下:

 public boolean equals(Object obj) {
if(obj instanceof Person){
Person p = (Person) obj;
if(p.getName()==null || name==null){
return false;
}else{
return name.equalsIgnoreCase(p.getName());
}
}
return false;
}