本来应该是写第7条的,但是发现我对第7条讲的东西不是很理解,所以就暂时先跳过,以后可能会遇到这样的章节也会跳过,写错误导别人罪过就大了。
覆盖equal方法看起来似乎很简单,但有很多覆盖方式会导致错误并导致很严重的后果。避免这类问题最简单的方法当然就是不覆盖equal方法。那么,我们要知道在哪些情况下就不需要覆盖equal方法呢?
只要满足下面任何一条,就可以,
1、类的每个实例本质上都是唯一的。对于代表活动实体而不是值的类,比如:Thread.
2、不关心类是否提供了“逻辑相等”的测试功能。比如:java.util.Random。
3、超类已经覆盖了equals,从超类继承过来的行为对于子类也是合适的。例如:大多数 的Set实现都是从AbstractSet继承的。还有List的实现,Map的实现。
4、类是私有的或是包级私有的,可以确定它的equals方法永运不会被调用。
5、用实例受控来确保“每个值至多只存在一个对象”的类,比如枚举类型。这样的类逻辑相同与对象相同是一回事。
那么,什么时候应该覆盖Object.equals呢?如果类有自己特有的“逻辑相等”,并且超类没有覆盖equals来实现期望的行为,这时需要覆盖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。如果y.equals(x) ==true,且y.equals(z) ==true,那么必须有z.equals(x) ==true。
4、对于任何非null的引用值x,必须有x.equals(null)==false;
书中给出几条实现高质量equals方法的诀窍:
1、使用==操作符检查“参数是否为这个对象的引用”,如果是,返回true。
2、使用instanceof操作符检查“参数是否为正确的类型”。如果是,返回true。一般所谓的正确的类型是指equals方法所在的那个类。有些时候是指该类所实现的某个接口。
3、把参数转换成正确的类型。
4、对于该类中的每个“关键”域,检查参数中的域是否与该对象中对应的域相匹配。如果这些测试全部成功,返回true,否则返回false。
5、当写完equals方法后,应该问自己三个问题:它是否是对称的、传递的、一致的?这些是要编写单元测试来验证的。
最后还有几点告诫:
覆盖equals方法时总要覆盖hashCode
不要企图让equals方法过于只能。
不要将equals声明中的Object对象替换为其它的类型。
分享到:
相关推荐
- **项03:覆盖equals时请遵守通用约定**:正确的equals方法实现对于确保对象一致性至关重要。 #### 代码设计原则 - **项04:始终覆盖hashCode**:当重写了equals方法时,必须同时重写hashCode方法以保持一致性。 ...
Joshua Bloch 所著《Effective Java 第二版》一书摘要这是我对 Joshua Bloch 所著《Effective Java 第 2 ... 覆盖equals时遵守一般约定9.重写equals时务必重写hashCode10. 始终覆盖toString11.明智地覆盖克隆12.考虑实
第8章 使用规范 193 8.1 数组 193 8.2 attribute 195 8.3 集合 198 8.3.1 集合参数 199 8.3.2 集合属性与返回值 200 8.3.3 数组与集合之间的选择 204 8.3.4 自定义集合的实现 205 8.4 ICloneable ...
第8章 使用规范 193 8.1 数组 193 8.2 attribute 195 8.3 集合 198 8.3.1 集合参数 199 8.3.2 集合属性与返回值 200 8.3.3 数组与集合之间的选择 204 8.3.4 自定义集合的实现 205 8.4 ICloneable ...
- 懒汉式:在第一次调用时创建实例。 8. **final关键字** - 标识常量或不可变对象。 - final类不能被继承,final方法不能被覆写。 9. **抽象类** - 包含抽象方法的类称为抽象类。 - 抽象类不能被实例化。 10...