[Effective Java 读书笔记] 第三章 对所有对象都通用的方法 第八 ---- 九条

这一章主要讲解Object类中的方法, Object类是所有类的父类,所以它的方法也称得上是所有对象都通用的方法

第八条 覆盖equals时需要遵守的约定

Object中的equals实现,就是直接对对象进行相等的比较:

    public boolean equals(Object obj) {
        return (this == obj);
    }

那么什么时候需要覆盖equals呢?

当你的类有自己的逻辑相等,而不是对象相等时,应该自己实现equals,比如Date和Interger,他们的相等比较不仅是对象相等,需要涉及到内部值的相等,

// Integer的equals实现:    
    public boolean equals(Object obj) {
        if (obj instanceof Integer) {
            return value == ((Integer)obj).intValue();
        }
        return false;
    }
// Date的equals实现:
    public boolean equals(Object obj) {
        return obj instanceof Date && getTime() == ((Date) obj).getTime();
    }

equals方法的实现必须满足等价关系(温习一下数学基本概念):

1.自反性。对于任何非null的引用值x,x.equals(x) 必须为true

2.对称性。对于非null的x和y,x.equals(y)推导出y.equals(x)

3.传递性。非null的xyz,x.equals(y) 并且y.equals(z),那么x.equals(z)

   这里讨论了一个典型例子。自类扩展了父类,增加了新的值组件(变量),那么equals很难在父类子类之间同时生效,比如父类的equals就缺少子类的新增变量的比较,子类的equals来比较父类,父类缺少子类新增的变量。

   文中提出了一种方法,基于组合优先于继承的原则,将子类独立出来,增加自己的值组件,并在子类中实现父类的实例,这样可以同时用equals比较这两部分

4.一致性。任何非null的xy,只要equals的比较操作在对象中所用的信息没有改变,多少次操作得到的值应该一样

5.非空性。一般并不需要在equals里显示的检查null == obj,因为 if (obj instanceof Integer) {}已经做了这个工作

关于写equals的几个建议:

1.优先使用==检查是否为这个对象的引用

2.使用instanceof检查参数是否为正确类型

3.equals覆盖时总要覆盖hashcode(),见第九条

4.不要让equals太智能太复杂

5.不要讲equals的参数改为其他类型,应该为Object

第九条 覆盖equals时总要覆盖hashCode

集合的操作都是基于散列的,比如从hashmap get 元素,先通过hashcode获取散列码,通过散列码找到对应的散列桶((hash bucket),然后在散列桶中通过equals找打对应的对象

所以,如果对象有同样的equals值,他们的hashcode应该也是相等的(Object规范 JAVA SE6);

反过来,有同样的hashCode,他们的eqauls值不一定要相同!

在计算散列码的过程中,如果equals中没有用到的域(比如成员变量),hashCode中也最好不要!

书中讲了一些简单的方法来获取hashCode,对于Integer,就是返回int value,boolean返回1或者0,我们看一下String的源码:

    public int hashCode() {
        int h = hash;
        if (h == 0 && value.length > 0) {
            char val[] = value;

            for (int i = 0; i < value.length; i++) {
                h = 31 * h + val[i];
            }
            hash = h;
        }
        return h;
    }

String类会将string转换为value这样一个数(private final char value[])
所以就是对数组的每一个元素进行处理,最后获取到散列值组合

原文地址:https://www.cnblogs.com/jiangz222/p/4774430.html