《Effective Java》读书笔记(二)之对于所有对象都通用的方法
第八条 在改写equals的时候请遵守通用约定
一般以下几种情况,不适宜覆盖equals方法
1.类的每个实例本质上都是唯一的,对于代表活动实体而不是值的类确实如此,例如Thread.
2.不关心类是否提供了“逻辑相等”的测试功能
3.超类已经覆盖了equals,从超类继承过来的行为对子类也是合适的
4.类是私有的或者包级私有的,可以确定它的equals方法永远不会被调用。
那什么情况应该覆盖Object.equals呢?如果类具有自己特有的“逻辑相等”的概念(不同于对象等同的概念),而且超类没有覆盖equals以实现期望的行为,就需要进行覆盖,这通常属于“值类”的情形,例如Integer和Date。当使用equals来比较对象, 是希望他们在逻辑上是否相等, 而不是指向同一对象, 或者用来作为Map的key以及集合Set中的元素时, 就必须复写equals方法.
实例受控,确保“每个值最多只存在一个对象”的类,枚举通常属于这种类型。对于枚举类型来说, 逻辑相等与对象相等是同一回事, 因此不需要覆盖equals方法。
equals的改写规范:
1)自反性:对于任何非null的引用值x,x.equals(x)一定为true
2)对称性:对于任何非null的引用值x和y,当且仅当x.dquals(y)为true;那么y.equals(x)也必须为true
3)传递性:对于任何非null的引用值x和y和z,如果x.equals(y)为true,y.equals(z);那么x.equals(x)也必须为true
4)一致性:对于任何非null的引用值x和y,如果用于equals比较的对象信息没有被修改的话,那么多次调用x.dquals(y)返回的值是一致的
5)对于非null引用值x,x.equals(null)一定返回false
接下来是逐一解析上面几个原则:
2)对称性
public final class CaseInsensitiveString {
private final String s;
public CaseInsensitiveString(String s) {
if (s == null)
throw new NullPointerException();
this.s = s;
}
// Broken - violates symmetry!
@Override
public boolean equals(Object o) {
if (o instanceof CaseInsensitiveString)
return s.equalsIgnoreCase(((CaseInsensitiveString) o).s);
if (o instanceof String) // One-way interoperability!
return s.equalsIgnoreCase((String) o);
return false;
}
// This version is correct.
// @Override public boolean equals(Object o) {
// return o instanceof CaseInsensitiveString &&
// ((CaseInsensitiveString) o).s.equalsIgnoreCase(s);
// }
public static void main(String[] args) {
CaseInsensitiveString cis = new CaseInsensitiveString("Polish");
String s = "polish";
System.out.println(cis.equals(s) + " " + s.equals(cis));
}
}
上面代码中的equals企图和String进行比较操作,假设我们有一个不区分大小的字符串和一个普通的字符串:
CaseInsensitiveString cis = new CaseInsensitiveString("Test");
String s = "test";
此时cis.equals(s)会返回true,CaseInsensitiveString 类中做了兼容大小写的处理,但是String 的equals方法是不知道要不区分大小写1的,所以s.equals(cis)会返回false,违反了自反性
假如你把CaseInsensitiveString 放到一个集合中
List<CaseInsensitiveString> list = new ArrayList<>();
list.add(cis);
list.contains(s);
list.contains(s)有可能返回true,也可能是false,甚至会抛出RumtimeException
为了解决这个问题,只要企图与String互操作的这段代码从equals去掉即可
@Override
public boolean equals(Object o) {
return o instanceof CaseInsensitiveString&&s.equalsIgnoreCase(((CaseInsensitiveString) o).s);
}
3)传递性:
首先以一个简单不可变的二维整形Point类作为开始
《Effective Java》读书笔记(二)之对于所有对象都通用的方法的更多相关文章
- 《Effective Java》第3章 对于所有对象都通用的方法
第8条:覆盖equals时请遵守通用约定 覆盖equals方法看起来似乎很简单,但是有许多覆盖方式会导致错误,并且后果非常严重.最容易避免这类问题的办法就是不覆盖equals方法,在这种情况下,类的每 ...
- 《Effective Java》第2章 对所有对象都通用的方法
第10条:覆盖equals时,请遵守通用约定 1.使用==来比较两个对象的时候,比较的是两个对象在内存中的地址是否相同(两个引用指向的是否为同一个对象):Object中定义的equals方法也是这样比 ...
- Java高效编程之二【对所有对象都通用的方法】
对于所有对象都通用的方法,即Object类的所有非final方法(equals.hashCode.toString.clone和finalize)都有明确的通用约定,都是为了要被改写(override ...
- Effective Java 读书笔记之一 创建和销毁对象
一.考虑用静态工厂方法代替构造器 这里的静态工厂方法是指类中使用public static 修饰的方法,和设计模式的工厂方法模式没有任何关系.相对于使用共有的构造器来创建对象,静态工厂方法有几大优势: ...
- 【Effective Java读书笔记】创建和销毁对象(一):考虑使用静态工厂方法代替构造器
类可以提供一个静态方法,返回类的一个静态实例,如Boolean包装类的一个获取实例的静态方法 public static Boolean valueOf(boolean b) { return (b ...
- [Effective Java 读书笔记] 第三章 对所有对象都通用的方法 第八 ---- 九条
这一章主要讲解Object类中的方法, Object类是所有类的父类,所以它的方法也称得上是所有对象都通用的方法 第八条 覆盖equals时需要遵守的约定 Object中的equals实现,就是直接对 ...
- Effective Java:对于全部对象都通用的方法
前言: 读这本书第1条规则的时候就感觉到这是一本非常好的书.可以把我们的Java功底提升一个档次,我还是比較推荐的.这里我主要就关于覆盖equals.hashCode和toString方法来做一个笔记 ...
- [Effective Java]第三章 对所有对象都通用的方法
声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...
- Effective java读书笔记
2015年进步很小,看的书也不是很多,感觉自己都要废了,2016是沉淀的一年,在这一年中要不断学习.看书,努力提升自己 计在16年要看12本书,主要涉及java基础.Spring研究.java并发.J ...
- Effective Java读书笔记完结啦
Effective Java是一本经典的书, 很实用的Java进阶读物, 提供了各个方面的best practices. 最近终于做完了Effective Java的读书笔记, 发布出来与大家共享. ...
随机推荐
- [HAOI2017模拟]囚人的旋律
没有传送门辣. 神奇的DP题. 首先看到这道题第一眼应该想到正解不是在图上搞,肯定要把原图转化成序列. 根据逆序对的性质.每个点和标号大于他的点连边的点,其权值必定要小于该点,而没和他连边的且标号大于 ...
- APP接口版本不兼容怎么办? 教你一招
现在基本每个公司都做APP,所以大家都面临 APP接口版本兼容的问题. iOS和android 要不断开发新版本,很多服务端开发都是在以前接口的逻辑上进行修改.新的APP和接口开发后,接口如何兼容老的 ...
- 20145301Java课程总结
20145301 Java课程总结 每周读书笔记链接汇总 第一周读书笔记: http://www.cnblogs.com/5301z/p/5248888.html 第二周读书笔记: http://ww ...
- linux 块设备-整理(一)
1. 基本概念: linux设备驱动开发详解(宋宝华): 字符设备与块设备 I/O 操作的不同如下. (1)块设备只能以块为单位接受输入和返回输出,而字符设备则以字节为单位. 大多数设备是字符设备,因 ...
- db2 xml 转 table
版本:DB2 Version 9.1 1.创建测试表,初始化数据 create table emp (doc XML); INSERT INTO EMP VALUES ('<dept bldg= ...
- NSURLSession 的学习资料
一个nsurlsession的一些学习资料 http://www.cocoachina.com/ios/20161018/17785.html
- codeforces 1A - math - ceil
2017-08-24 15:42:30 writer: pprp 感觉自己好菜啊,这个题都没有做的很好 题意很简单,用a * a 的地砖,将 n * m 的地板铺满,问最少需要多少个地砖? 一开始打算 ...
- 02_Storm集群部署
1. 部署前的硬件及软件检查 硬件要求 1)storm集群部署包括zookeeper部署,而zookeeper集群最小为3台机器2)storm的计算过程都在内存中完成,因此内存要尽量大3)storm少 ...
- IDEA.环境
1.下载: https://www.jetbrains.com/idea/download/#section=windows 安装的版本是:Ultimate:ideaIU-2017.3.3.exe 2 ...
- 手机APP测试环境搭建---appium
这些都不是重点---一切都可以参考虫师 Appium移动自动化测试(一)--安装Appium 1.ADB的安装:ADB(ANDROID DEBUG BRIDGE) 应用场景: 针对移动端 Andr ...