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

[改善Java代码]equals应该考虑null值的情景的更多相关文章

  1. [改善Java代码]提防包装类型的null值

    建议26: 提防包装类型的null值 我们知道Java引入包装类型(Wrapper Types)是为了解决基本类型的实例化问题,以便让一个基本类型也能参与到面向对象的编程世界中.而在Java 5中泛型 ...

  2. [改善Java代码]别让null值和空值威胁到变长方法

    建议5:别让null值和空值威胁到变长方法 public class Client { public void methodA(String str,Integer... is){ } public ...

  3. [改善Java代码]不要在finally块中处理返回值

    在finally代码块中处理返回值,这是在面试题中经常出现的题目.但是在项目中绝对不能再finally代码块中出现return语句,这是因为这种处理方式非常容易产生"误解",会严重 ...

  4. [改善Java代码]非稳定排序推荐使用List

    我们知道Set与List的最大区别就是Set中的元素不可以重复(这个重复指的equals方法的返回值相等),其他方面则没有太大的区别了,在Set的实现类中有一个比较常用的类需要了解一下:TreeSet ...

  5. [改善Java代码]用枚举实现工厂方法模式更简洁

    工厂方法模式(Factory Method Patter)是"创建对象的接口",让子类决定实例化哪一个类,并使一个类的实例化延迟到其子类.工厂方法模式在我们的开发工作中,经常会用到 ...

  6. [改善Java代码]不同的场景使用不同的泛型通配符

    Java泛型支持通配符(Wildcard),可以单独使用一个"?"表示任意类,也可以使用extends关键字标识某一类(接口)的子类型,还可以使用super关键字标识某一类(接口) ...

  7. [改善Java代码]避免带有变长参数的方法重载

    建议4: 避免带有变长参数的方法重载 在项目和系统的开发中,为了提高方法的灵活度和可复用性,我们经常要传递不确定数量的参数到方法中,在Java 5之前常用的设计技巧就是把形参定义成Collection ...

  8. [改善Java代码]自由选择字符串拼接方法

    对一个字符串拼接有三种方法:加号,contact方法,StringBuffer或者StringBuilder的append方法,其中加号是最常用的.其他两种方式偶尔会出现在一些开源项目中,那么这三者有 ...

  9. [改善Java代码]正确使用String,StringBuffer,StringBuilder

    CharSequence接口有三个实现类与字符串有关:String,StringBuffer,StringBuffer.虽然它们都与字符串有关,但是其处理机制是不同的. String类是不可改变的量, ...

随机推荐

  1. Can jxta be used to develop online card game (p2p style)?

    Can jxta be used to develop online card game (p2p style)? https://www.java.net//node/677134 I am new ...

  2. struts2+Hibernate4+spring3+EasyUI环境搭建之三:引入sututs2以及spring与sututs2整合

    1.引入struts2 <!-- struts2 和心包 排除javassist 因为hibernate也有 会发生冲突--> <dependency> <groupId ...

  3. PLSQL Developer 常用设置及快捷键

    1.登录后自动选中My Objects(已验证可用) 默认情况下,PLSQL Developer登录后,Brower里会选择all Objects,如果你登录的用户是DBA, 要展开tables目录, ...

  4. HDU 5762 Teacher Bo (暴力)

    Teacher Bo 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5762 Description Teacher BoBo is a geogra ...

  5. POJ Wormholes (SPFA)

    http://poj.org/problem?id=3259 Description While exploring his many farms, Farmer John has discovere ...

  6. LCA + 二分(倍增)

    两个最近的点u和v的最近的公共的祖先称为最近公共祖先(LCA).普通的LCA算法,每算一次LCA的时间复杂度为线性o(n); 这里讲LCA + 二分的方法.首先对于任意的节点v,利用其父节点的信息,可 ...

  7. -webkit-appearance: none;去处select默认小箭头样式

    Html <select class="sel_house_type"> <option value="0">请选择</optio ...

  8. c++未指定返回值

    int foo() { } foo返回的是随机数 函数的返回值在函数堆栈的参数后面,由一个指向寄存器的指针决定,函数返回时,调用者取指针取寄存器中的值作为返回值. 如果指定返回值,函数在返回前会将返回 ...

  9. 理解Windows中的路由表和默认网关

    每一个Windows系统中都具有IP路由表,它存储了本地计算机可以到达的网络目的地址范围和如何到达的路由信息.路由表是TCP/IP通信的基础,本地计算机上的任何TCP/IP通信都受到路由表的控制. 理 ...

  10. OA系统权限管理设计(转载)

    不论什么系统都离不开权限的管理,有一个好的权限管理模块,不仅使我们的系统操作自如,管理方便,也为系统加入亮点. l         不同职责的人员,对于系统操作的权限应该是不同的.优秀的业务系统,这是 ...