《Effective Java》知识点(2)--对于所有对象都通用的方法

10. 覆盖equals时请遵守通用约定

10.1  不要轻易覆盖equals方法,除非迫不得已。因为:

10.1.1 类的每个实例本质上都是唯一的。

10.1.2 类没有必要提供”逻辑相等“的测试功能。

10.1.3 超类已经覆盖了equals,超类的行为对于这个类也是合适的。

10.1.4 类是私有的,或者是包级私有的,可以确定它的equals方法永远不会被调用。

10.2  如果要覆盖equals方法,必须遵守5个通用约定

10.2.1 自反性(reflexive):x!=null && x.equals(x)==true

10.2.2 对称性(symmetric):x!=null && y!=null &&  x.equals(y)==true &&  y.equals(x)==true

10.2.3 传递性(transitive):x!=null && y!=null && z!=null &&  x.equals(y)==true &&  y.equals(z)==true, then  x.equals(z)==true

10.2.4 一致性(consistent):x!=null && y!=null,多次调用x.equals(y)的返回值固定不变

10.2.5 (非空性):x!=null && x.equals(null)==false

    一旦违反了约定,当其它对象面对你的对象时,完全不知道这些对象的行为会怎么样!

10.3  实现equals方法的几个诀窍

10.3.1 使用==操作符检查”参数是否为这个对象的引用“

10.3.2 使用instanceof 操作符检查”参数是否为正确的类型“

10.3.3 把参数转换成正确的类型

10.3.4 对于该类中的每个”关键“域,检查参数中的域是否与该对象中的域相匹配

10.3.5 完成equals方法后,编写单元测试来检验5个约定,特别是对称性、传递性和一致性

10.3.6 覆盖equals方法时总要覆盖hashCode

10.3.7 不要企图让equals方法过于智能

10.3.8  不要将equals声明中的Object对象替换为其它的类型(实际上并未覆盖Object.equals)

11.  覆盖equals时总要覆盖hashCode

       若不覆盖hashCode,这个类无法和HashMap\HashSet一起正常工作。

       相等的对象必须具有相等的hash code。

       习惯上使用素数来计算散列结果,31可以用移位和减法来代替乘法。

       不要试图从散列码计算中排除掉一个对象的关键域来提高性能。

       不要对hashCode方法的返回值做出具体的规定。

12.  始终要覆盖toString

       提供好的toString实现可以使类用起来更加舒适,系统也更易于调试。       

        toString方法应该返回对象中包含的所有值得关注的信息,给返回格式添加注释。

        应该为toString返回值中包含的所有信息提供可以通过编程访问的方法。 

13.  谨慎地覆盖clone

       不可变的类永远都不应该提供clone方法。

       clone方法就是另一个构造器,必须确保它不会伤害到原始的对象,并确保正确地被克隆对象中的约束条件。

       对象拷贝的最好方法是提供一个拷贝构造器或拷贝工厂。但如果是数组,最好利用clone方法拷贝数组。

14.  考虑实现Comparable接口

        实现一个对排序敏感的类时,应该实现Comparable接口,这样可以与许多泛型算法协作。

        在compareTo方法中比较域值时,应避免使用<和>操作符(繁琐且容易出错),而应该在装箱基本类型的类中使用静态的compare方法,或者在Comparator接口中使用比较器构造方法。

        通用约定:

14.1 对称性:sgn(x.compareTo(y) == -sgn(y.compareTo(x), 或都抛出异常

14.2 传递性:x.compareTo(y)>0 && y.compareTo(z)>0,then x.compareTo(z)>0

14.3 x.compareTo(y)==0, then sgn(x.compareTo(z) == sgn(y.compareTo(z)

14.4 强烈建议 (x.compareTo(y)==0) == (x.equals(y))

 

你可能感兴趣的:(Java,java,开发语言)