假设我创建了一个对象并将其添加到数组列表中。如果我然后用完全相同的构造函数输入创建另一个对象,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吗?
记录重写等于
你说:
另一个具有完全相同构造函数输入的对象
还有……
假设构造函数没有对输入做任何奇怪的事情,并且存储在两个对象中的变量是相同的。
正如其他答案解释的那样,您必须重写object# equals方法,以便list# contains工作。
在Java 16+中,记录功能会自动为您覆盖该方法。
记录是编写类的一种简单方式,其主要目的是透明且不变地传递数据。默认情况下,只需声明成员字段。编译器隐式创建构造函数、getter、equals & hashCode和toString。
默认情况下,等号逻辑是将一个对象的每个成员字段与同一类的另一个对象中的对应项进行比较。同样,hashCode和toString方法的默认实现也考虑每个成员字段。
record Thing( int amount ) {} ;
就是这样,这就是一个功能完整的只读类所需的所有代码,不需要任何常见的样板代码。
使用例子。
Thing x = new Thing( 100 ) ;
Thing y = new Thing( 100 ) ;
boolean parity = x.equals( y ) ;
运行时。
奇偶校验= true
回到你的列表#包含问题。
Thing x = new Thing( 100 );
List < Thing > things =
List.of(
new Thing( 100 ) ,
new Thing( 200 ) ,
new Thing( 300 )
);
boolean foundX = things.contains( x );
运行时。
foundX = true
附加特性:可以在方法中本地声明一条记录。或者像传统的类一样,可以将记录声明为嵌套类或单独的类。
其他帖子已经解决了contains()如何工作的问题。
您的问题中同样重要的一个方面是如何正确地实现equals()。这个问题的答案取决于这个特定类的对象相等的构成。在你提供的例子中,如果你有两个x=5的不同对象,它们相等吗?这真的取决于你想要做什么。
如果你只对对象的相等性感兴趣,那么.equals()的默认实现(由object提供的)只使用标识符(即this == other)。如果这是你想要的,那么就不要在你的类上实现equals()(让它从Object继承)。你写的代码,虽然是正确的,如果你是为了标识,永远不会出现在一个真正的类b/c,它提供没有使用默认的Object.equals()实现的好处。
如果您刚刚开始学习这些东西,我强烈推荐Joshua Bloch的《Effective Java》一书。这是一本很棒的读物,涵盖了这类内容(以及当您试图做更多基于标识的比较时如何正确实现equals())