Java 为单个类实现多个equals方法

Java 为单个类实现多个equals方法,java,equals,comparator,Java,Equals,Comparator,我有课要讲 class Dog { String name; int age; String collarType; } 我已经重写了equals方法来比较所有3个字段,以确定2只狗是否相等 现在我有一个情况,我有2个Dog对象,即使2个Dog实例的collarType不同,它们也可以相等。因此,我不能使用我的equals方法 使用新模式编写比较器(仅比较姓名和年龄)并检查compare(Dog d1,Dog d2)是否返回0是最好的方法吗?正如您所注意到的,平等性对用

我有课要讲

class Dog {
    String name;
    int age;
    String collarType;
}
我已经重写了
equals
方法来比较所有3个字段,以确定2只狗是否相等

现在我有一个情况,我有2个
Dog
对象,即使2个
Dog
实例的
collarType
不同,它们也可以相等。因此,我不能使用我的
equals
方法


使用新模式编写比较器(仅比较姓名和年龄)并检查
compare(Dog d1,Dog d2)
是否返回
0
是最好的方法吗?

正如您所注意到的,平等性对用户来说是主观的。然而,唯一真正“正确”的等式应该是对象上的等式(这可能是完全等价的,因为如果有一个不那么严格的版本是正确的,那就很奇怪了)。这个等式应该说,在任何情况下,物体1和物体2是不可能的,如果它们相等的话

其他(“主观”)方法应该通过比较器实现,是的,我确实认为您应该使用比较器。此外,您应该适当地命名该比较器(如NameAndAgeComparator),以区分两者,因为您还可以设想DogRaceComparator和SizeComparator按大小排序


为了方便起见,您可以(可能)为比较器提供一个静态equals方法,这将允许您使用静态导入来引用它,比如
equals(dog1,dog2)
。但那只是我的2美分

你的班级应该是这样的:

class Dog 
{
    final String name;
    final Integer age;
    final String collarType;

    public boolean equals(Object other) 
    {
       return this.name.equals(other.name) && 
              this.age.equals(other.age) &&
              this.collarType.equals(other.collarType);
    }
}
如果这些属性中有任何一个是可变的,那么你的问题就属于更为突出的类别

如果这些字段中的任何一个与equals无关,则应为不同的
类型

名为()的公共接口{public String name();} 公共接口老化(){public String age(TimeUnit TimeUnit);} 公共接口可折叠{public String collarType();}

那么你有:

public class Dog implements Named, Aged, Collarable { /* brevity */ }
并提供这些接口的自然
比较器
比较器
比较器
实现。

  • 如果将其放入任何类型的映射或集合,则实现等于和哈希代码
  • 如果要对它们进行排序,请实现Compariable接口,但它应该与实现的equals和hashcode方法兼容
  • 如果要按Equals和hashcode方法以外的其他字段对列表进行排序/比较,请使用Comparator实现

为了什么目的,你需要知道它们是否相等?番石榴有一个名为的类,可以用于此目的。对我来说,这似乎是倒退的:平等测试应该只使用不变字段,如姓名(变化的可能性较低)、出生日期(而不是更容易变化的年龄),而不是可以一时兴起改变的collarType。它取决于您想要比较
Dog
实例的上下文。如果您想使用集合或类似的方法对它们进行排序,那么实现一个比较器是一个不错的选择。如果您只需要一个额外的equals方法,只需将其作为
Dog
的实例方法实现即可。当然,只有原始的
equals
方法才能使用
=
,您必须通过其名称调用第二个equals:
dog1.equalByNameAndAge(dog2)
或类似方法。@gmazlami只是为了澄清,Java中的==运算符从不“调用”.equals()方法。==比较对象引用或基本体。