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

建议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 } 

 

posted @ 2016-04-25 16:36  SummerChill  阅读(5839)  评论(0编辑  收藏  举报