重写equals方法时要遵循通用约定--EffectiveJava小结(8)

不覆盖(重写)equals的情况下:只有s1==s2,才有s1.equals(s2).
Object中equals的实现如下:

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

重写equals方法要遵循的通用约定有
1.自反性:对于非null对象x,有x.equals(x) == true.
如果违反了自反性,集合的contains方法就无法判断该对象已经存在了。

class Test1 {
        
        @Override
        public boolean equals(Object obj) {
            return false;
        }
    }
    
    
public static void test1() {
        EqualsMethod_8 obj = new EqualsMethod_8();
        
        List tests = new ArrayList<>();
        Test1 test = obj.new Test1();
        tests.add(test);
        System.err.println(tests.contains(test));
        //返回false
    }

2.对称性:在x.equals(y)为true的同时必须y.equals(x)也为true。
就像一个等式,不能因为等式左右两边换了个位置就不成立了。如果违反了这个原则则可能导致难以预料得错误。因为你不能控制调用者掉的是x.equals(y),y.equals(x),而且这也不应该是需要关心的事。

比如ArrayList的contains方法。其具体实现是调用传入对象o.equals(elementData[i]),如果不遵守对称性,如果以后ArrayList具体实现使用elementData[i].equals(o),那得出来的结果可能就大相径庭了。

    public boolean contains(Object o) {
        return indexOf(o) >= 0;
    }
    
    public int indexOf(Object o) {
        if (o == null) {
            for (int i = 0; i < size; i++)
                if (elementData[i]==null)
                    return i;
        } else {
            for (int i = 0; i < size; i++)
                if (o.equals(elementData[i]))
                    return i;
        }
        return -1;
    }

3.传递性:x.equals(y),y.equals(z)都为true,则x.equals(z)为true。
主要考虑子类的情况,child1.equals(parent),parent.equals(child2)并不能代表child1.equals(child2)。child1,child2可能拥有的参数类型和个数都不相同。

4.一致性:如果x.equals(y)为true,那么在x,y被修改之前,x.equals(y)一直为true。也就是说对于不可变对象x,y,x.equals(y)结果始终一致。
这条原则主要考虑equals方法不要依赖不可靠资源,应该用内存中明确有的资源做计算。如:一个url如果只判断url的字符串是否相等那是可靠的,但是如果要先通过url获取资源在判断是否相等那就是不可靠的。

5.非空性:所有对象必须不能和null相等。
可以显式地判断null

        if (obj == null) {
                return false;
            }

但是可能这个判断是多余的,因为可能你本来就需要判断instanceof,那么就可以不用判断null了,因为(null instanceof Test1)为false。

        if (!(obj instanceof Test1)) {
                return false;
            }

你可能感兴趣的:(重写equals方法时要遵循通用约定--EffectiveJava小结(8))