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

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



1 public class Client {  
2 public static void main(String[] args) {
3 Person p1 = new Person("张三");
4 Person p2 = new Person(null);
5
6 List<Person> l =new ArrayList<Person>();
7 l.add(p1);
8 l.add(p2);
9 System.out.println("列表中是否包含张三:"+l.contains(p1));
10 System.out.println("列表中是否包含张三 :"+l.contains(p2));
11 }
12 }
13
14 class Person{
15 private String name;
16
17 public Person(String _name){
18 name = _name;
19 }
20
21 @Override
22 public boolean equals(Object obj) {
23 if(obj instanceof Person){
24 Person p = (Person) obj;
25 return name.equalsIgnoreCase(p.getName().trim());
26 }
27 return false;
28 }
29
30 public String getName() {
31 return name;
32 }
33
34 public void setName(String name) {
35 this.name = name;
36 }
37 }


很小的改动,那运行结果是什么呢?是两个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代码如下:



1 public boolean equals(Object obj) {  
2 if(obj instanceof Person){
3 Person p = (Person) obj;
4 if(p.getName()==null || name==null){
5 return false;
6 }else{
7 return name.equalsIgnoreCase(p.getName());
8 }
9 }
10 return false;
11 }


 


作者:SummerChill