我正在浏览 Joshua Bloch 关于“覆盖 equals() 方法”的在线章节。这是链接。以下部分让我感到困惑,
反身性——第一个要求只是说一个对象必须等于它自己。很难想象无意中违反了这一要求。如果您违反它然后将您的类的实例添加到集合中,那么集合的 contains 方法几乎肯定会说该集合不包含您刚刚添加的实例。
问题 - 集合的包含方法是否有可能在添加到其中的实例上返回 false?
我试过了,但返回的结果总是正确的。
我正在浏览 Joshua Bloch 关于“覆盖 equals() 方法”的在线章节。这是链接。以下部分让我感到困惑,
反身性——第一个要求只是说一个对象必须等于它自己。很难想象无意中违反了这一要求。如果您违反它然后将您的类的实例添加到集合中,那么集合的 contains 方法几乎肯定会说该集合不包含您刚刚添加的实例。
问题 - 集合的包含方法是否有可能在添加到其中的实例上返回 false?
我试过了,但返回的结果总是正确的。
问题 - 集合的包含方法是否有可能在添加到其中的实例上返回 false?
除非添加的对象equals()
违反了合同,正如书中的引文所解释的那样。
正如@Karthik T 所建议的那样,尝试使用一个equals()
无条件返回的对象false
(从而违反合同)。
为了说明这一点,有这个简单的类:
class C {
private int i;
public C(int i) { this.i = i; }
}
现在,如果你这样做:
C c1 = new C(1);
C c2 = new C(1);
List<C> l = new ArrayList<C>();
l.add(c1);
l.contains(c2)
将返回false
,因为c2.equals(c1)
is false
,尽管两个实例具有相同的构造函数参数。
这是因为 classC
不会覆盖.equals()
nor .hashCode()
。
一般来说,每次你的类必须用于Collection
任何类型的时候,你最好重写这两个方法。在这种情况下:
// Note: final class, final member -- that makes this class immutable
final class C {
private final int i;
public C(int i) { this.i = i; }
@Override
public int hashCode() { return i; }
@Override
public boolean equals(Object o)
{
// no object equals null
if (o == null)
return false;
// an object is always equal to itself
if (this == o)
return true;
// immutable class: if the class of the other is not the same,
// objects are not equal
if (getClass() != o.getClass())
return false;
// Both objects are of the same class: check their members
return i == ((C) o).i;
}
}
这是一个集合的 contains 方法的演示,该方法为刚刚添加到集合中的对象返回 false。我采用了由 Eclipse 生成的普通 equals 和 hashCode,并将 equals 方法更改为非自反的。具体来说,当将对象与自身进行比较时,它会返回 false。
import java.util.LinkedList;
import java.util.List;
public class Test {
int someValue;
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + someValue;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
// Bad. Non-reflexive. Should return true.
return false;
}
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Test other = (Test) obj;
if (someValue != other.someValue)
return false;
return true;
}
public static void main(String[] args) {
List<Test> myList = new LinkedList<Test>();
Test myObject = new Test();
myList.add(myObject);
System.out.println(myList.contains(myObject));
}
}