【问题标题】:hashCode() called on array instance in Java [duplicate]在Java中的数组实例上调用的hashCode()[重复]
【发布时间】:2014-06-24 11:34:45
【问题描述】:

我刚写代码,突然在Netbeans中看到这个警告:

hashCode() 在数组实例上调用

发生在这段代码中:

public class SomeObject {

    private String a;
    private char[] b;

    @Override
    public boolean equals(Object anotherObject) {
        if (!(anotherObject instanceof SomeObject)) {
            return false;
        }
        SomeObject object = (SomeObject) anotherObject;
        return (this.a.equals(object.a) && arraysAreEqual(this.b, object.b));
    }

    // When I created the equals() method, Netbeans warned me:
    // 'Generate missing hashCode()'. Okay then, here it comes:

    @Override
    public int hashCode() {
        return (43 * this.a.hashCode() + 11 * this.b.hashCode()); // MARKED LINE.
    }
}

警告出现在标记的行上。 IDE 发现我应该避免在数组实例上调用 hashCode()

现在我为什么要避免在数组上使用hashCode()

请注意,我阅读了this question and answer,但他们没有提到这一点。

【问题讨论】:

  • 如果内存服务,数组继承默认的hashCode() 实现,所以也许这就是原因。
  • Riiight。这就说得通了。似乎这个问题有它的重复。

标签: java arrays hashcode


【解决方案1】:

Java 数组直接派生自java.lang.Object,因此继承了equalshashCode 方法。

默认equals 方法比较对象身份(即两个引用是否引用相同 对象),默认hashCode 方法很可能会为不同的对象返回不同的值。

在大多数情况下,这是您不希望出现的行为。您很可能希望根据 content 比较数组。请注意,您的 equals 方法似乎可以做到这一点,这反过来意味着您的 hashCode 方法已损坏。原因看method's documentation

正是出于这个原因,Java 提供了一个带有辅助方法的类:java.util.Arrays。它提供了方法equalshashCode,这两个方法都是基于数组的内容。

所以你应该这样写:

public class SomeObject {

    private String a;
    private char[] b;

    @Override
    public boolean equals(Object anotherObject) {
        if (!(anotherObject instanceof SomeObject)) {
            return false;
        }
        SomeObject object = (SomeObject) anotherObject;
        return (this.a.equals(object.a) && Arrays.equals(this.b, object.b));
    }

    @Override
    public int hashCode() {
        return (43 * this.a.hashCode() + 11 * Arrays.hashCode(this.b));
    }
}

【讨论】:

    【解决方案2】:

    我会更好地使用:

    java.utils.Arrays.hashCode(char[] a)
    

    http://www.tutorialspoint.com/java/util/arrays_hashcode_char.htm

    以您的方式,您不是在测试 char 数组的内容。

    java.util.Arrays.hashCode(char[]) 方法返回一个基于哈希码 在指定数组的内容上。对于任何两个 char 数组 a 和 b 使得 Arrays.equals(a, b),它也是这样的情况 Arrays.hashCode(a) == Arrays.hashCode(b)。

    public void testHashCode() {
    
        char[] b = { 'a', 'b' };
        char[] a = { 'a', 'b' };
        System.out.println("HashCode b:" + b.hashCode() + " a:" + a.hashCode());
        System.out.println("Array hashCode a:" + java.util.Arrays.hashCode(a) + " b:" + java.util.Arrays.hashCode(b));
    }
    

    结果:

    HashCode b:8995841 a:8995844
    Array hashCode a:4066 b:4066
    

    希望这会有所帮助!

    【讨论】:

    • 呃,toString() 不是继承自 Object 的数组吗?所以这基本上和普通的hashCode()一样没用?
    • 你是对的。最好的选择是第一个。添加了一个测试
    • 如果您要包含替代方案,也许您应该建议比toString() 更有用的东西?
    • 完全同意。我改变了答案。
    【解决方案3】:

    问题是您不能覆盖array,它使用默认的hashCode() 实现,这可能会导致问题。您可以将其视为设计疏忽。您应该将arrays 包装在任意对象中,或者不要在arrays 的上下文中完全使用hashCode()

    【讨论】:

      【解决方案4】:

      数组的hashCode 实现基于数组的标识而不是内容。在大多数情况下,这不是您想要的,因为具有相同内容的两个数组通常具有不同的哈希码。

      要使哈希码基于数组的内容,您可以使用java.utils.Arrays.hashCode 方法。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-03-27
        • 2013-08-06
        • 2013-01-16
        • 2014-10-17
        • 2013-10-13
        • 1970-01-01
        • 2013-06-11
        • 1970-01-01
        相关资源
        最近更新 更多