Java ArrayList.containsAll不使用我的自定义等于函数

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);

下面的代码是一个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));
如您所见,类中有一个
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;
}