尽管Object是一个具体的类,但设计它主要是为了扩展。它的所有非final方法都有明确的通用约定。任何一个类在override时,必须遵守这些通用约定。
一、覆盖equals时请遵守通用的约定
1、Object中默认的equals方法约定是:类的每个实例都只与它自身相等。当类有自己特有的“逻辑相等”的概念时,就应该覆盖equals方法。
2、Timestamp对Date进行了扩展,Timestamp的equals实现确实违反了对称性。如果Timestamp和Date混合一起使用,可能导致不正确的行为。
3、不要使equals方法依赖于不可靠的资源。
4、实现高质量equals方法的诀窍是:
a、使用==操作符检查”参数是否为这个对象的引用“。
b、使用instanceof操作符检查”参数是否为正确的类型“。
c、把参数转变成正确的类型。
d、对于该类中的每个关键域,检查参数中的域是否与该对象中对应的域相匹配。
e、完成equals方法后,检查是否对称、传递和一致。
注意:
a、覆盖equals方法后,一定要覆盖hashCode方法。
b、不要让equals方法过于智能。
c、不要将equals声明中的Object对象替换成其他类型。借助@Override可解决此问题。
二、覆盖equals时总要覆盖hashCode
1、如果覆盖了equals方法却不覆盖hashCode方法将导致该类无法和基于散列的集合一起正常运作。
2、相等的对象必须有相等的散列码。
3、equals方法和hashCode方法最好使用相同的域。在计算散列码时,加入乘法使得散列码是顺序相关的,更加严谨和合理。
4、对于不可变类,散列码可进行缓存和赖加载优化。
5、不要试图从散列码计算中排除掉一个对象的关键部分来提高性能。
三、始终要覆盖toString方法
1、提供好的toString方法可以是类用起来更加舒适。
2、toString方法返回对象中包含的所有值得关注的信息。
3、是否制定返回值的格式可以根据实际情况来定。
4、对于toString返回值包含的所有信息,提供一种编程式的访问途径。
四、谨慎地覆盖clone方法
1、Cloneable接口的目的是作为对象的一个mixin接口,没有包含任何方法。它决定了Object中受保护的clone方法实现的行为。
2、实现了Cloneable的类,我们总是期望它也提供一个功能适当的公有的clone方法。
3、clone方法就是另一个构造器,你必须确保它不会伤害到原始的对象,并确保正确地创建被克隆对象中的约束条件。
4、拷贝构造器和拷贝工厂是实现对象拷贝的好办法。所有通用集合都实现了一个拷贝构造器。
5、尽量不去覆盖clone方法,也从来不去使用它,除非拷贝数组。
五、考虑实现Comparable接口
1、comparaTo方法不是Object中的方法,而是Comparable接口中唯一的方法。该方法不仅可进行等同性比较,还可以进行顺序比较。
2、接口的通用约定是按照equals方法来定义的,但有序集合使用了compareTo方法的等同性测试。
3、如果是是一个值类,而且具有明显的内在排序关系,就因该坚决实现该接口。