《Effective Java》读书笔记——覆盖equals时请遵守通用约定
来源:互联网 发布:奇策软件 编辑:程序博客网 时间:2024/05/16 15:29
public boolean equals(Object obj) { return (this == obj); }
一.什么时候不需要覆盖equals()方法?
1.类的每个实例本质上都是唯一的。例如枚举类型,或者Thread类,他们的每一个实例都是唯一的。
2.不关心是否提供了“逻辑相等”的测试功能。
3.超类已经覆盖了equals()方法,从超类继承过来的行为对于子类也是适合的。
4.类是私有的或者包级私有的,可以确定他的equals()方法永远不会被调用。
二.什么时候需要覆盖equals()方法?
如果类具有自己特定的“逻辑相等”概念。而且超类还没有覆盖equals()方法以实现期望的行为,这时我们就应该需要覆盖equals()方法。通常,需要覆盖equals()方法的类属于“值类”,值类是仅仅表示一个值的类,例如Integer类,程序员使用这些类的equals()方法比较对象的引用时,是希望知道它们在逻辑之上是否相等,而不是想知道它们是否指向同一个对象。
三.覆盖equals()方法的时候需要遵守的约定
1.自反性:对于任何非null的引用值x,x.equals(x)必须返回true。
2.对称性:对于任何非null的引用值x和y,当且仅当y.equals(x)返回true的时候,x.equals(y)也必须返回true。
3.传递性:对于任何非null引用值x、y和z,如果x.equals(y)返回true,并且y.equals(z)也返回true,那么x.equals(z)也必须返回true。
4.一致性:对于任何非null的引用值x和y,只要equals()的比较操作在对象中所用的信息没有被修改,那么多次调用equals()方法必须返回相同的结果。
5.对于任何非null的引用值x,x.equals(null)必须返回false。
四.常见的违背equals约定的例子
1.对称性:
public final class CaseInsensitiveString {private final String s;public CaseInsensitiveString(String s){if(s == null)throw new NullPointerException();this.s = s;}@Overridepublic boolean equals(Object obj) {if(obj instanceof CaseInsensitiveString)return s.equalsIgnoreCase(((CaseInsensitiveString) obj).s);if(obj instanceof String)return s.equalsIgnoreCase((String) obj);return false;}public static void main(String[] args) {CaseInsensitiveString c = new CaseInsensitiveString("Person");String s = "person";System.out.println(c.equals(s));System.out.println(s.equals(c));}}
在这个例子中,CaseInsensitiveString的equals()方法的目的是与普通的字符串进行操作,equals()方法知道普通的字符串,所以可以进行比较,但是String类中却不知道CaseInsensitiveString类,所以比较结果是false,这就违反了对称性,所以上面的equals()方法中不能有与String相互操作的代码部分。3.传递型:
public class Point {private final int x;private final int y;public Point(int x,int y){this.x = x;this.y = y;}@Overridepublic boolean equals(Object obj) {if(!(obj instanceof Point))return false;Point p = (Point) obj;return p.x == x&&p.y == y;}}这是一个普通的点的类,接着可能他还有一个子类,就是为这个点着色:
public class ColorPoint extends Point {private final Color color;public ColorPoint(int x, int y ,Color color) {super(x, y);this.color = color;}}
如果这个类不覆盖父类的equals()方法,这样做不会违背equals的约定,但是颜色却会被忽略,所以必须覆盖equals()方法。public boolean equals(Object obj) {if(!(obj instanceof ColorPoint))return false;return super.equals(obj)&&((ColorPoint) obj).color == color;}
上面的equals()方法在比较普通点和有色点的时候,可能会出现不同的结果,违背对称性。所以这种方式不行。<pre name="code" class="java">public boolean equals(Object obj) {if(!(obj instanceof Point))return false;if(!(obj instanceof ColorPoint))return obj.equals(this);return super.equals(obj)&&((ColorPoint) obj).color == color;}上面的equals()方法满足了对称性,但是却违背的传递性,比如有三个点,分别是(1,3,Color.RED)、(1,3)、(1,3,Color.BLUE),第一个点与第二个点比较返回true,第二个点与第三个点比较也返回true,但是第一个点与第三个点之间比较会返回false,这就违背了传递性。这是因为我们无法在扩展可实例化的类的同时,既增加新的组件,同时又保留equals的约定。解决的办法是我们采用复合优先于继承,我们不让ColorPoint类扩展Point,而是在ColorPint类中加入一个私有的Point域。
public boolean equals(Object obj) {if(!(obj instanceof ColorPoint))return obj.equals(this);ColorPoint cp = (ColorPoint)obj;return cp.point.equals(obj)&&cp.color == color;}
五.实现高质量的equals()方法的诀窍
1.使用==操作符检查“参数是否为这个对象的引用”,如果是则返回true。这只是一种性能优化的手段。
2.使用instanceof操作符检查“参数是否为正确的类型”,如果不是,则返回false。
3.把参数转换成正确的类型。
4.对于该类中的每个关键域,检查参数中的域是否与该对象中对应的域相匹配。
5.检查该类是否满足对称性、传递性、一致性。
6.其他注意事项
1.覆盖equals()方法的时候总是要覆盖hashCode()方法。
2.不要让equals()方法过于智能。
3.不要将equals()声明的中的Object对象替换为其他的类型
- 覆盖equals时请遵守通用约定——Effective Java 读书笔记
- 《Effective Java》读书笔记——覆盖equals时请遵守通用约定
- effective java (8) 覆盖equals时请遵守通用约定
- Effective Java读书笔记-覆盖equals时遵守的通用约定
- Effective Java 第八条:覆盖equals请遵守通用约定
- Effective Java(避免使用最终方法、覆盖equals时请遵守通用约定)
- 覆盖equals时请遵守通用约定
- 覆盖equals时请遵守通用约定。
- 《Effective Java》读书笔记07--覆盖equals时要遵守通用约定
- Effective Java 对于所用对象都通用的方法 8.覆盖equals时请遵守通用约定.txt
- 第8条:覆盖equals时请遵守通用约定
- 第8条:覆盖equals时请遵守通用约定
- 第8条:覆盖equals时请遵守通用约定
- 第八条:覆盖equals时请遵守通用约定
- 第8条:覆盖equals时请遵守通用约定
- Effective Java 第8条:覆盖equals时要遵守通用约定
- 《Effective java》读书记录-第8条-覆盖equals时需要遵守通用约定
- effective java(8) 之覆盖equals时遵守通用的约定
- CentOS安装
- 使<select>中的文字居中
- 彻底理解position与anchorPoint
- play框架配置自定义404页面
- Hadoop — Linux(Ubuntu15.04)下安装`配置Hadoop(2.6.0)
- 《Effective Java》读书笔记——覆盖equals时请遵守通用约定
- Jersey VS Django-Rest
- Java并发编程:Callable、Future和FutureTas
- .net实现裁剪网站上传图片的方法
- Caffe框架,图像数据转换成LMDB数据格式
- [记录]Java网络爬虫基础和抓取网站数据的两个小实例
- 判断回文数字
- PL/SQL调用JAVA发布的Web Service示例
- oracle通配符过滤(模糊匹配)