以下代码是JUnit测试函数,在执行时失败。
List<KGramPostingsEntry> a = new ArrayList<KGramPostingsEntry>();
List<KGramPostingsEntry> b = new ArrayList<KGramPostingsEntry>();
KGramPostingsEntry entry = new KGramPostingsEntry(1);
a.add(entry);
entry = new KGramPostingsEntry(1);
b.add(entry);
assertTrue(a.containsAll(b));
它使用KGramPostingsEntry
类:
package ir;
public class KGramPostingsEntry {
int tokenID;
public KGramPostingsEntry(int tokenID) {
this.tokenID = tokenID;
}
public KGramPostingsEntry(KGramPostingsEntry other) {
this.tokenID = other.tokenID;
}
public String toString() {
return tokenID + "";
}
public boolean equals(KGramPostingsEntry other) {
if(other.tokenID == this.tokenID) {
return true;
}
return false;
}
}
如您所见,该类中有一个equals()
函数,用于比较不同tokenID
个对象的KGramPostingsEntry
。在我看来,在测试中调用containsAll()
时不使用此函数。进一步的实验似乎证实了这一点:
List<KGramPostingsEntry> a = new ArrayList<KGramPostingsEntry>();
List<KGramPostingsEntry> b = new ArrayList<KGramPostingsEntry>();
KGramPostingsEntry entry = new KGramPostingsEntry(1);
a.add(entry);
b.add(entry);
assertTrue(a.containsAll(b));
在这里,我在两个列表中插入相同的对象。此测试不会失败。就我收集的内容而言,ArrayList
在存储对该对象的引用之前,将对象的副本对象发送到add()
。这意味着两个List
中的对象不相同(即使它们具有相同的tokenID
),并且containsAll()
不检查对象引用相等性。但是,如果它没有检查对象引用相等性并且没有检查我的代码中定义的equals()
函数,它会检查什么?对我来说唯一合理的选择是它检查对象值相等,并且第一个测试示例中存储的两个对象以某种方式不同(即使它们唯一的属性是tokenID
,两个对象都是一样的。)
这里发生了什么?如何以我想要的方式使测试成功?
答案 0 :(得分:4)
equals方法没有正确的签名。它应该是
__exit__
答案 1 :(得分:4)
此处equals
的{{1}}声明:
Object
(documentation)。您正在尝试覆盖此方法,而是重载:
public boolean equals(Object obj)
注意方法中的参数类型是public boolean equals(KGramPostingsEntry other)
,它与KGramPostingsEntry
中的参数类型不同,即Object.equals
。当一个方法具有相同的名称但不同的参数类型时,它会被重载,而不会被覆盖。
当Object
尝试将其内容与ArrayList
进行比较时,它会使用最适用的equals
覆盖版本。遗憾的是,这并不包括你的方法。
幸运的是,修复很简单:您需要使用Object.equals
参数实现equals
方法:
Object