Java ArrayList.containsAll不使用我的自定义等于函数
下面的代码是一个JUnit测试函数,在执行时失败Java ArrayList.containsAll不使用我的自定义等于函数,java,unit-testing,arraylist,junit,Java,Unit Testing,Arraylist,Junit,下面的代码是一个JUnit测试函数,在执行时失败 List<KGramPostingsEntry> a = new ArrayList<KGramPostingsEntry>(); List<KGramPostingsEntry> b = new ArrayList<KGramPostingsEntry>(); KGramPostingsEntry entry = new KGramPostingsEntry(1); a.add(entry);
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));
如您所见,类中有一个equals()
函数,用于比较不同KGramPostingsEntry
对象的tokenID
。在我看来,在测试中调用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));
List a=new ArrayList();
列表b=新的ArrayList();
KGramPostingsEntry=新KGramPostingsEntry(1);
a、 添加(条目);
b、 添加(条目);
资产真实性(a.b));
这里,我在两个列表中插入相同的对象。此测试不会失败。据我所知,ArrayList
在存储对该对象的引用之前,为发送到add()
的对象创建一个副本对象。这意味着两个列表中的对象不相同(即使它们具有相同的tokenID
),并且containsAll()
不会检查对象引用是否相等。但是,如果它不检查对象引用相等性,也不检查我的代码中定义的equals()
函数,它会检查什么?对我来说,唯一可行的选择是它检查对象值相等,并且第一个测试示例中存储的两个对象在某种程度上是不同的(即使它们唯一的属性是tokenID
,这在两个对象中是相同的)
这是怎么回事?如何使此测试以我希望的方式成功?equals方法没有正确的签名。应该是
public boolean equals(Object that) {
// ..
}
这里的等于对象的声明
:
public boolean equals(Object obj)
()。您试图重写此方法,但却重载了它:
请注意,方法中的参数类型是KGramPostingsEntry
,它与Object.equals
中的参数类型不同,即Object
。当一个方法具有相同的名称但参数类型不同时,它将被重载,而不是被重写
当ArrayList
尝试将其内容与equals
进行比较时,它将使用最适用的对象.equals的重写版本。不幸的是,这不包括你的方法
幸运的是,修复很容易:您需要使用对象
参数实现equals
方法:
public boolean equals(Object obj) {
if(obj == null || !(obj instanceof KGramPostingsEntry)) {
return false;
}
KGramPostingsEntry other = (KGramPostingsEntry) obj;
if(other.tokenID == this.tokenID) {
return true;
}
return false;
}
谢谢你能详细解释一下为什么它必须有那个签名吗?@sah否则它是一个不同的方法,这个方法不会被List的实现调用来确定List是否包含这个对象。列表将调用this.equals(Object obj2)
,它继承自Object
类,因为您没有重写它。当您实现equals()
时,不要忘记实现一个hashCode()
,您应该包括:,@Override这样,当您犯此错误时,编译器将警告您。请注意,用@Override
注释该方法将捕获此错误。事实上,这正是注释的目的。
public boolean equals(KGramPostingsEntry other)
public boolean equals(Object obj) {
if(obj == null || !(obj instanceof KGramPostingsEntry)) {
return false;
}
KGramPostingsEntry other = (KGramPostingsEntry) obj;
if(other.tokenID == this.tokenID) {
return true;
}
return false;
}