【问题标题】:Incorrectly overriding the equals method for hashSets in Java错误地覆盖 Java 中 hashSets 的 equals 方法
【发布时间】:2017-04-27 16:48:18
【问题描述】:

我有以下代码:

public class Trooper {
private String name;
private boolean mustached;
public Trooper(String name, boolean hasMustache) {
    this.name = name; this.mustached = hasMustache;
}
public String getName() { return name; }
public boolean hasMustache() { return mustached; }
public boolean equals(Trooper other) {
    if (this == other) return true;
    if (null == other || !(other instanceof Trooper)) return false;
    Trooper that = (Trooper) other;
    return this.name.equals(that.name) && this.mustached == that.mustached;
}
public int hashCode() { return 1; }
}

然后运行如下:

ArrayList<Trooper> troopers = new ArrayList<>();
troopers.add(new Trooper("Farva", true));
troopers.add(new Trooper("Farva", true));
troopers.add(new Trooper("Rabbit", false));
troopers.add(new Trooper("Mac", true));
Set<Trooper> trooperSet = new HashSet<>(troopers);

为什么下面的代码返回false?

trooperSet.contains(new Trooper("Mac", true));

我了解在调用 contains 方法时如何在 hashSet 中使用 hashCode 和 equals。我能猜到它返回 false 而不是 true 的唯一原因是 equals 方法没有被正确覆盖。如果这是上一条语句返回 false 的原因,为什么会这样?

【问题讨论】:

    标签: java overriding equals hashcode hashset


    【解决方案1】:

    您正在重载 equals() 方法,而不是覆盖它。 Here's the differenceequals() 的正确签名是:

    public boolean equals(Object other) {
        ...
    }
    

    HashSet 永远不会使用您当前的 equals()。相反,Object#equals() 被使用,因此结果。

    顺便说一句,包含@Override 标签可以帮助发现这些错误。

    【讨论】:

      【解决方案2】:

      您正在重载 equals() 方法,而不是覆盖它。

      Object.equals() 定义为:public boolean equals(Object obj) 通过将参数指定为类型 Trooper,您定义了一个新的方法签名。

      使用@Override 注释确实有助于捕获这样的错误;注释会警告你你实际上并没有覆盖任何东西。 (像 IntelliJ 这样好的 IDE 中的静态检查也会发现这一点,但这并不是每个人都喜欢的。)

      【讨论】:

        猜你喜欢
        • 2020-01-30
        • 2020-06-09
        • 1970-01-01
        • 1970-01-01
        • 2014-05-27
        • 2010-09-16
        • 1970-01-01
        • 2015-02-25
        相关资源
        最近更新 更多