1

我只是在探索 hashCode() 方法的不同实现。我打开了 java.lang.Integer 类,找到了 hashCode() 的这个实现:

public int hashCode() {
        return Integer.hashCode(value);
}

public static int hashCode(int value) {
        return value;
}

我的问题是,为什么实现不能这么简单:

public int hashCode(){
    return this.value;
}

需要创建一个额外的静态方法来传递值并返回相同的值吗?我在这里忽略了任何重要的细节吗?

4

2 回答 2

1

该代码在单独查看时确实看起来很奇怪。

但请注意静态方法java.lang.Integer.hashCode

  • 后来在 Java 8 中添加
  • public

Java 14中的源代码没有显示任何注释来解释为什么要添加这个静态方法。因为方法是public,所以我认为这个新的静态方法在 Java 8 的一些新特性中起作用,可能与流有关,在OpenJDK代码库的其他地方被调用。

如 Javadoc 中所述,为了保持一致性Integer::hashCode,重写了现有实例方法的源代码以调用静态方法。hashCode这样,只有一个地方实际生成哈希码。对于代码库的审查和维护来说,只有一个地方是明智的。

制作hashCode静态当然是不寻常的。该hashCode方法的目的是将该类的一个对象标识为另一个对象,以便在诸如HashSet或之类的集合中使用HashMaphashCode鉴于我们正在通过方法比较实例,因此成为实例方法而不是静态方法是有意义的。

HotSpotOpenJ9等优化编译器可能会内联hashCode方法调用,从而使源代码中的实例方法与静态方法排列变得毫无意义。

于 2020-07-18T01:10:37.057 回答
1

@Basil Bourque 的回答几乎涵盖了所有内容。但他留下了为什么要public static void hashCode(int)添加的问题。

2012 年 11 月在此变更集中进行了更改

变更集的标题和摘要是这样说的:

7088913:将兼容的静态 hashCode(primitive) 添加到原始包装类

摘要:向每个原始包装类添加静态实用程序方法,以允许从未装箱的原始类型计算 hashCode 值。

请注意,变更集没有记录变更的动机。

我推断增强的一个目的是避免应用程序程序员必须知道原始包装类是如何计算的。在 Java 8 之前,要计算原始的包装兼容哈希码int,程序员必须编写

  int value = ...
  int hash = ((Integer) value).hashCode();  // Facially inefficient (depending on
                                            // JIT compiler's ability to get
                                            // rid of the box/unbox sequence)

或者

  int value = ...
  int hash = value;                         // Hardwires knowledge of how 
                                            // Integer.hashCode() is computed.

虽然“知识”对于int/Integer来说是微不足道的,但考虑 / 的情况,double其中Double哈希码计算是:

  long bits = doubleToLongBits(value);
  return (int)(bits ^ (bits >>> 32));

似乎这个变更集受到了 Streams 项目的推动。例如,Integer::hashCode可以在整数流中使用。

但是,添加 和用于流减少的变更集发生在此之后的几个月所以我们不能明确地建立联系……基于这个证据。summinmax

于 2020-07-18T01:59:29.183 回答