不覆盖(重写)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<Test1> 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;
}
网友评论