建议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. HDU 5816 Hearthstone (状压DP)

    Hearthstone 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5816 Description Hearthstone is an onlin ...

  2. codeforces 630C Lucky Numbers

    C. Lucky Numbers time limit per test 0.5 seconds memory limit per test 64 megabytes input standard i ...

  3. ThinkPHP框架的网站url重写

    nginx location / { root /var/www; index index.html index.htm index.php; if (!-e $request_filename) { ...

  4. POJ 3237 Tree (树链剖分 路径剖分 线段树的lazy标记)

    题目链接:http://poj.org/problem?id=3237 一棵有边权的树,有3种操作. 树链剖分+线段树lazy标记.lazy为0表示没更新区间或者区间更新了2的倍数次,1表示为更新,每 ...

  5. Unity中2D和UGUI图集的理解与使用

    图集 什么是图集? 在使用3D技术开发2D游戏或制作UI时(即使用GPU绘制),都会使用到图集,而使用CPU渲染的2D游戏和UI则不存在图集这个概念(比如Flash的原生显示列表),那么什么是图集呢? ...

  6. 无废话C#设计模式系列文章

    不错的系列文章 原文:http://www.cnblogs.com/lovecherry/archive/2007/10/17/927728.html 本系列文章从公司内部的知识分享修改而来,有错误或 ...

  7. 读《C# 和 Java 的比较》有感

    网上的一篇<C# 和 Java 的比较>(或者叫<Java 和 C# 的比较>)写的挺不错的,今天忽然搜索到. 自己刚刚接触C#,也不由自主地随时都拿来和Java做对比,所以就 ...

  8. iOS strong 和weak的形象理解

    转自:http://hi.baidu.com/phone_lwc/item/c36e5bfe1cf9c313ce9f32be 觉得讲的很容易理解 The difference is that an o ...

  9. 日志分析(五) PV&UV

    应用设计请求之初,对于url有一定的规划.因此,请求的url格式类似如下: /**/school/****?token=a66cb2a3-e0b7-4f0a-b332-********* token唯 ...

  10. Mac OS 10.10 Yosemite正式版怎么升级 升级教程

    苹果在2014年10月17号凌晨一点召开了新品发布会,推出了新的 iPad.iMac 产品,以及大家一直所期盼的 Mac OS 10.10 正式版系统.个人是从 Mac OS 10.10 的第一个测试 ...