0

我正在浏览 Joshua Bloch 关于“覆盖 equals() 方法”的在线章节。这是链接。以下部分让我感到困惑,

反身性——第一个要求只是说一个对象必须等于它自己。很难想象无意中违反了这一要求。如果您违反它然后将您的类的实例添加到集合中,那么集合的 contains 方法几乎肯定会说该集合不包含您刚刚添加的实例。

问题 - 集合的包含方法是否有可能在添加到其中的实例上返回 false?

我试过了,但返回的结果总是正确的。

4

3 回答 3

1

问题 - 集合的包含方法是否有可能在添加到其中的实例上返回 false?

除非添加的对象equals()违反了合同,正如书中的引文所解释的那样。

正如@Karthik T 所建议的那样,尝试使用一个equals()无条件返回的对象false(从而违反合同)。

于 2013-01-05T16:25:51.250 回答
1

为了说明这一点,有这个简单的类:

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;
    }
}
于 2013-01-05T16:28:35.317 回答
0

这是一个集合的 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));
  }
}
于 2013-01-05T16:56:39.043 回答