在Java中覆盖hashcode和equals方法?

3

我有以下类:

public class Sample implements java.io.Serializable{

  //POJO with two fields and getters/setters

   private String name;
   private Integer id;

   //This POJO does not override equals() and hashCode()
}

public class B{
 private Sample sample;

  //here i need override hashcode and equals() based on **sample** property.


}

当我尝试在B类中重写equals()和hashCode()方法时,在Eclipse中出现了以下错误:

字段类型com.mypackage.Sample没有实现hashCode()和equals()方法-生成的代码可能无法正常工作。

现在我该如何比较两个基于Sample属性是否相等的B实例?我不能修改Sample类。

2
可能是[当超类没有重新声明equals()和hashCode()时会出什么问题?]的重复。(https://dev59.com/8WQo5IYBdhLWcg3wMtC2) 不过请注意,我认为这个警告是错误的 - Duncan Jones
1
Eclipse是一个保姆。它会替你担心。你可以忽略它或者将方法添加到样例中。 - bmargulies
了解比较器和可比较接口吗? - dev2d
2个回答

2

你是否在寻找类似以下的东西?只需要尝试一下,因为从你的问题中我认为你想要比较你的样本类的内容。

class Sample implements java.io.Serializable{

    //POJO with two fields and getters/setters

    private String name;
    private Integer id;

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }

    //This POJO does not override equals() and hashCode()
}

public class Beta implements Comparable{
    private Sample sample;

    public Sample getSample() {
        return sample;
    }

    public void setSample(Sample sample) {
        this.sample = sample;
    }

    @Override
    public int compareTo(Object o) {

        if(!(o instanceof Beta)){
            return -1;
        }
        }if(((Beta)o).getSample().getName().equals(this.sample.getName())){
                return 0; // return true if names are equal
            }
            if(((Beta)o).getSample().getId().equals(this.sample.getId())){
            //if name are notequal and IDs are equal, do what you need to do
            }
        return -1;
    }

    public static void main(String[] args) {
        Beta b = new Beta();
        Sample s = new Sample();
        s.setId(10);
        s.setName("Name1");
        b.setSample(s);

        Beta b2 = new Beta();
        Sample s2 = new Sample();
        s2.setId(20);
        s2.setName("Name2");
        b2.setSample(s2);

        System.out.println(b2.compareTo(b));

        Beta b3 = new Beta();
        Sample s3 = new Sample();
        s3.setId(10);
        s3.setName("Name1");
        b3.setSample(s3);

        System.out.println(b3.compareTo(b));
    }
}

覆盖方法

class Sample implements java.io.Serializable{

    //POJO with two fields and getters/setters

    private String name;
    private Integer id;

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }

    //This POJO does not override equals() and hashCode()
}

public class Beta /*implements Comparable*/{
    private Sample sample;

    public Sample getSample() {
        return sample;
    }

    public void setSample(Sample sample) {
        this.sample = sample;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final Beta other = (Beta) obj;

        if ((this.getSample() == null) && (other.getSample() == null)){
            return true;
        }
        if ((this.getSample().getId().equals(other.getSample().getId())) && (this.getSample().getName().equals(other.getSample().getName()))) {
            return true;
        }
        return false;
    }

    @Override
    public int hashCode() {
        int hash = 3;
        hash = 53 * hash + (this.getSample().getName() != null ? this.getSample().getName().hashCode() : 0);
        hash = 53 * hash + (this.getSample().getId() != null ? this.getSample().getId().hashCode() : 0);
        return hash;
    }


/*  @Override
    public int compareTo(Object o) {

        if(!(o instanceof Beta)){
            return -1;
        }
        if(((Beta)o).getSample().getId().equals(this.sample.getId()) && ((Beta)o).getSample().getName().equals(this.sample.getName())){
            return 0;
        }
        return -1;
    }*/

    public static void main(String[] args) {
        Beta b = new Beta();
        Sample s = new Sample();
        s.setId(10);
        s.setName("Name1");
        b.setSample(s);

        Beta b2 = new Beta();
        Sample s2 = new Sample();
        s2.setId(20);
        s2.setName("Name2");
        b2.setSample(s2);

        System.out.println(b2.equals(b));

        Beta b3 = new Beta();
        Sample s3 = new Sample();
        s3.setId(10);
        s3.setName("Name1");
        b3.setSample(s3);

        System.out.println(b3.equals(b));
    }

VD,是的,这正是我在寻找的。我的要求是首先需要检查Sample对象的“name”属性是否等于equals属性。如果名称相同,则两个对象相等。如果名称不同,则需要检查Sample对象的“ID”属性是否相等。我该怎么做呢?谢谢! - user755806
我已经根据您的需求编辑了代码,您可以参考https://dev59.com/q2sy5IYBdhLWcg3w-zF5中的覆盖方法。 - dev2d
我还编辑了覆盖hashCode和equals方法的代码。 - dev2d

1
如果您没有显式覆盖.equals(),则它们将仅基于引用进行比较(尽管没有equals(),但每个对象都从Object继承一个)。如果您只想让B基于Sample进行比较,则只需执行以下操作:
@Override
public boolean equals(Object o)
{
     if (o istanceof B)
     {
         return sample.equals(o.sample)
     }

     return false;
}

此外,您还应该覆盖 hashCode()(和 compareTo())以维护equals()hashCode()之间的契约。因此,您还应具有以下内容:
@Override
public int hashCode()
{
    return sample.hashCode();
}

编辑(回应评论):

我的要求是首先需要检查Sample的“name”属性是否等于equals属性。如果名称相同,则两个对象相等。如果名称不相同,则需要根据Sample的“ID”属性检查相等性。我该如何做到这一点?谢谢!

确定样本是否相等应该在Sample中处理,通过覆盖equals()。如果Sampleequals()基于nameid,那么就没问题了。如果您想以不同于正常比较方式来比较B中的Samples,那么如果使用Sample中的hashCode()equals(),则无法维护Bequals()hashCode()之间的契约,这意味着BhashCode()equals()不能调用Sample中的equals()hashCode()。请参见此tutorial了解如何基于特定字段进行覆盖。

我尝试了,但仍然收到“字段类型com.mypackage.Sample未实现hashCode()和equals()方法-生成的代码可能无法正常工作”的错误。有什么建议吗? - user755806
@user755806 这绝对有效,我相信你的IDE只是告诉你没有显式地覆盖hashCode()equals()。确保你也已经覆盖了BhashCode() - 我进行了一次编辑,说明了如何做到这一点。如果没有这样做,那么你将无法维护equals()hashCode()的契约。如果你的IDE仍然警告你,那只是一个提醒,确保你理解对于Sample,你正在使用默认方法而不是覆盖它们。 - Steve P.
Steve,谢谢你的回复。我的要求是首先需要检查Sample对象的“name”属性是否与另一个对象相等。如果名称相等,则两个对象相等。如果名称不相等,则需要检查Sample对象的“ID”属性是否相等。我该怎么做呢?谢谢! - user755806
@user755806 这里你提出了多个问题...这应该在 Sample 中处理。也就是说,通过重写 Sample 中的 equals() 方法来实现。如果这不是比较 Samples 的正常方式,或者你无法这样做,那么你将无法维护 equals()hashCode() 的约定,这意味着你不能做你想做的事情。请参考这个教程,了解如何基于特定字段进行重写。 - Steve P.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接