Effective Java之覆盖equal时要遵守通用约定(八)
来源:互联网 发布:上海地铁线路图软件 编辑:程序博客网 时间:2024/05/16 19:40
先介绍一下Object的equal作用,==代表物理上的相等,equal代表逻辑上的相等,Object的equal的方法其实等同于==,这是因为它的逻辑是“如果对象物理相等,那么它们就逻辑相等”。
1.何时不需要覆盖
1.如果每个实例的本质是唯一的,也就是说只有自己才会等于自己,那么它的equal方法应该相当于它的==,所以它从Object继承过来的方法刚好满足条件了,不需要覆盖。
2.不关心它的“逻辑相等”,既然都不关心了,那还写什么?
3.超类覆盖的equal方法,对子类同样适用的情况下,就不用覆盖了。比如Set实现了从AbstractSet继承的方法,所以它不用去覆盖了。
2.何时需要覆盖
1.有的类的equal永远也不会调用的情况,那么应该覆盖equals方法,让它在调用时抛出错误。
2.如果希望定义特有的”逻辑相等”的情况,可以覆盖equals,比如定义市民类,如果两个市民的身份证字段相等,那么两个市民类相等,这样的逻辑。
3.覆盖需要遵守的约定
在覆盖equals方法时,必须遵守它的通用约定:
1)自反性: x.equals(x) 必须返回true 。实例自身必然逻辑相等。
2)对称性: x.equals(y) 与 y.equals(x) 返回结果应该相同,同为true或者同为false
3)传递性: x.equals(y)返回true,y.equals(z)返回true,则x.equals(z)应该返回true。
4)一致性: 只要比较的实例对象的关键属性值没有改变 ,那么无论调用多少次equals方法返回的结果都应该相同,一致。
5)对于非null的x实例,x.equals(null) 永远返回false。
这一章的内容十分地充实,这里,我只能总结一下书中重要的内容:
1.不要企图让一个类和一个它的非子类进行equal对比,比如 市民类.equal(String identity),
希望只要市民的身份证号等于字符串类型的identity就返回true,这样是不可行的,因为必然会违反对称性,除非你能去修改String类?
2.我们无法在扩展可实例化的类的同时,既增加新的值组件,同时又保留equal约定。
也就是遇到可实例化的父类和子类,而且子类扩展了父类的问题时,会遇到很尴尬的问题,这里应该认真看一下书~
书中写到了父类和子类的各种纠缠~解决的一种方法,也可以说是权宜之计,就是割断父子关系。。
也就是利用复合优于继承的原则;原来的子类不是扩展了父类吗,那么我让父类成为原来子类的一个私有域,利用复合的方式组装一个类出来。既然不存在父子关系了,父子进行对比产生的种种纠缠也就不复存在了。
书中也有举到一个很有意思的例子,TimeStamp对Date进行扩展,增加了nanoseconds域,由于上面的规则“我们无法在扩展可实例化的类的同时,既增加新的值组件,同时又保留equal约定”,所以设计师也无法进行正确的操作,于是TimeStamp有个免责声明,告诫开发者不要同时使用TimeStamp和Date,也就是不让程序员纠缠在父子的问题上了。
这里有个里式替换原则,可以注意一下:一个类型的任何重要属性也将适用于它的子类型,因此为该类型编写的任何方法,在他的子类型也应该同样运行得很好。
4.如何使用?
1.先用“==”操作符号判断“参数是否为这个对象的引用”,如果是,那直接返回true。
这其实是一种性能优化,不进行这个操作也会得到一样的结果,所以需要根据每次比较的代价判断是否先用“==”,代价大就需要优化。
2.用instanceof检查“参数是否为正确的类型”。
3.再将参数object对象转成正确的类型。
4.自己定义“逻辑相等”。
5.写完有仔细思考有没有满足对称性,传递性,一致性。
例子:
public class Citizen { private String name ; private String Identity; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getIdentity() { return Identity; } public void setIdentity(String identity) { Identity = identity; } @Override public boolean equals(Object obj) { if(this == obj) { return true; } if(!(obj instanceof Citizen)) { return false; } Citizen citizen = (Citizen)obj; return this.getIdentity().equals(citizen.getIdentity()); }}
这里的 先用“==”操作符号判断“参数是否为这个对象的引用” 可以不需要。
- Effective Java之覆盖equal时要遵守通用约定(八)
- effective java (8) 覆盖equals时请遵守通用约定
- Effective Java读书笔记-覆盖equals时遵守的通用约定
- effective java(8) 之覆盖equals时遵守通用的约定
- 《Effective Java》读书笔记07--覆盖equals时要遵守通用约定
- Effective Java 第8条:覆盖equals时要遵守通用约定
- Effective Java 第八条:覆盖equals请遵守通用约定
- 《Effective Java》笔记之重写equals时要遵守的通用约定
- 覆盖equals时请遵守通用约定——Effective Java 读书笔记
- 《Effective Java》读书笔记——覆盖equals时请遵守通用约定
- 《Effective java》读书记录-第8条-覆盖equals时需要遵守通用约定
- Effective Java(避免使用最终方法、覆盖equals时请遵守通用约定)
- java对象通用方法之覆盖equals时请遵守通用约定、覆盖equals时总要覆盖hashCode、始终要覆盖toString、考虑实现Comparable接口
- Effective Java 对于所用对象都通用的方法 8.覆盖equals时请遵守通用约定.txt
- 覆盖equals时遵守通用约定
- 覆盖equals时请遵守通用约定
- 覆盖equals时请遵守通用约定。
- 第8条:覆盖equals时请遵守通用约定
- 津巴布韦交易所上市以太币,恢复比特币交易
- 理解RESTful架构
- 比特币高调登上主流舞台
- 澳大利亚比特币交易所必须在金融监管机构进行注册
- 德银罗列2018金融市场风险,比特币崩盘位列其中
- Effective Java之覆盖equal时要遵守通用约定(八)
- 云服务
- 大型黄金交易所APMEX开始接受比特币
- momentjs如何格式化时间差值
- java设计模式之模板设计模式和单例模式,以及复合
- 迭代器与组合模式
- Waves项目评估报告(中文报告全文下载)
- Zcash公布2018区块链升级路线图
- ProtoBufPaser工具使用教程