[以下固定问题]
我有这堂课:
Class Doc() {
private String D;
Doc(String d) {
D = d;
}
@Override
public boolean equals(Object o) {
if (o instanceOf String) {
if (o.equals(D)) return true;
else return false;
} else return false;
}
@Override
public int hashCode() {
...
}
}
如果我运行测试,请使用例如启动Doc() " ABC"作为参数,然后使用Doc().equals("abc")
它返回true - 正如我所料。如果我使用:
ArrayList docs = new ArrayList<Doc>();
Doc d = new Doc("123");
Docs.add(d);
System.out.println(docs.contains("123"));
它返回false,我不确定为什么。我已经尝试将输出添加到.equals()
方法以检查它是否已被使用,并且确实如此。 hashCode()
的代码只是一些虚假(我知道我应该做一些正确的事,我只是不确定如何) - 但我只会使用equals()
。
我在某处equals()
也会检查hashCode()
。如果我在System.out.println(".")
中添加hashCode()
作为第一行,则它不会输出任何内容,因此它似乎不会被调用。我最好的猜测是,我无法比较不同类别的两个对象 - 这是正确的吗?或者我忽略了其他什么?
为了将来参考,使用@JonSkeet的建议解决了这个问题 - 代码现在是:
Class Doc() {
private String D;
Doc(String d) {
D = d;
}
public String getD() {
return D;
}
@Override
public boolean equals(Object o) {
if (o instanceOf Doc) {
Doc tmp = (Doc) o;
if (tmp.getD().equals(D)) return true;
else return false;
} else return false;
}
@Override
public int hashCode() {
...
}
}
答案 0 :(得分:6)
您认为contains()
会致电memberInCollection.equals(candidate)
而不是candidate.equals(memberInCollection)
。 documentation与此相反:
更正式地说,当且仅当此列表包含至少一个元素e
(o==null ? e==null : o.equals(e))
时才返回true。
从根本上说,您的equals
方法违反了正常合同,因为它不是对称的 - 对于x
和y
的任何非空值,x.equals(y) == y.equals(x)
应该是真正。这是不你的代码的情况:
new Doc("123").equals("123") // True
"123".equals(new Doc("123")) // False
(此外,如果equals
是对x.equals(x)
实例的引用,那么x
方法甚至不具有反身性,Doc
永远不会成立。)
基本上,您不应该尝试使一个类型的实例等于不相关类型的实例。它总会很糟糕。在类型层次结构中很难使等式很好地工作 - 但对于不相关的类型,这是真的坏主意。