假设我创建了一个对象并将其添加到数组列表中。如果我然后用完全相同的构造函数输入创建另一个对象,contains()方法是否会计算出两个对象是相同的?假设构造函数没有对输入做任何奇怪的事情,并且存储在两个对象中的变量是相同的。

ArrayList<Thing> basket = new ArrayList<Thing>();  
Thing thing = new Thing(100);  
basket.add(thing);  
Thing another = new Thing(100);  
basket.contains(another); // true or false?

class Thing {  
    public int value;  

    public Thing (int x) {
        value = x;
    }

    equals (Thing x) {
        if (x.value == value) return true;
        return false;
    }
}

这是类应该如何实现有contains()返回true吗?


当前回答

class Thing {  
    public int value;  

    public Thing (int x) {
        value = x;
    }

    equals (Thing x) {
        if (x.value == value) return true;
        return false;
    }
}

你必须写:

class Thing {  
    public int value;  

    public Thing (int x) {
        value = x;
    }

    public boolean equals (Object o) {
    Thing x = (Thing) o;
        if (x.value == value) return true;
        return false;
    }
}

现在它工作了;)

其他回答

ArrayList实现了列表接口。

如果查看Javadoc for List中的contains方法,就会发现它使用equals()方法来计算两个对象是否相同。

它对对象使用equals方法。因此,除非Thing重写equals并使用存储在对象中的变量进行比较,否则它不会在contains()方法上返回true。

其他帖子已经解决了contains()如何工作的问题。

您的问题中同样重要的一个方面是如何正确地实现equals()。这个问题的答案取决于这个特定类的对象相等的构成。在你提供的例子中,如果你有两个x=5的不同对象,它们相等吗?这真的取决于你想要做什么。

如果你只对对象的相等性感兴趣,那么.equals()的默认实现(由object提供的)只使用标识符(即this == other)。如果这是你想要的,那么就不要在你的类上实现equals()(让它从Object继承)。你写的代码,虽然是正确的,如果你是为了标识,永远不会出现在一个真正的类b/c,它提供没有使用默认的Object.equals()实现的好处。

如果您刚刚开始学习这些东西,我强烈推荐Joshua Bloch的《Effective Java》一书。这是一本很棒的读物,涵盖了这类内容(以及当您试图做更多基于标识的比较时如何正确实现equals())

只是想指出,当value不是基本类型时,下面的实现是错误的:

public class Thing
{
    public Object value;  

    public Thing (Object x)
    {
        this.value = x;
    }

    @Override
    public boolean equals(Object object)
    {
        boolean sameSame = false;

        if (object != null && object instanceof Thing)
        {
            sameSame = this.value == ((Thing) object).value;
        }

        return sameSame;
    }
}

在这种情况下,我建议如下:

public class Thing {
    public Object value;  

    public Thing (Object x) {
        value = x;
    }

    @Override
    public boolean equals(Object object) {

        if (object != null && object instanceof Thing) {
            Thing thing = (Thing) object;
            if (value == null) {
                return (thing.value == null);
            }
            else {
                return value.equals(thing.value);
            }
        }

        return false;
    }
}
class Thing {  
    public int value;  

    public Thing (int x) {
        value = x;
    }

    equals (Thing x) {
        if (x.value == value) return true;
        return false;
    }
}

你必须写:

class Thing {  
    public int value;  

    public Thing (int x) {
        value = x;
    }

    public boolean equals (Object o) {
    Thing x = (Thing) o;
        if (x.value == value) return true;
        return false;
    }
}

现在它工作了;)