【问题标题】:what is the internal working of System.idendityHashCode() and hashCode() method?System.identityHashCode() 和 hashCode() 方法的内部工作是什么?
【发布时间】:2015-03-20 01:22:28
【问题描述】:

我阅读了关于 System.identityHashCode(Object x)。你不能覆盖它,因为它的静态方法,但我可以覆盖 Object's hashCode 方法。这也是 System.identityHashCode(Object x) 在 javadoc 中提到的:

为给定对象返回与默认方法 hashCode() 返回相同的哈希码,无论给定对象的类是否覆盖 hashCode()。空引用的哈希码为零。

但是当我通过在 println 方法中交换对象来运行下面的代码时,我得到了相同的结果。

public class SherlockGCD {
    public int hashCode()
      {
       return super.hashCode();
      }
    public static void main(String[] args) {
      SherlockGCD sher= new SherlockGCD();
      SherlockGCD sher1= new SherlockGCD();
      System.out.println(System.identityHashCode(sher));
      System.out.println(sher1.hashCode());
     }
    }

输出是:

31866429

16795905

但是如果你像下面这样交换对象,那么输出也是一样的

    System.out.println(System.identityHashCode(sher1));
    System.out.println(sher.hashCode());

输出是:

31866429

16795905

那么为什么输出没有反转,因为我正在更改 println 方法中的对象??

【问题讨论】:

    标签: java hashcode


    【解决方案1】:

    但是当我通过在 println 方法中交换对象来运行下面的代码时,我得到了相同的结果。

    您不应将hashCode 在一次运行中的结果与另一次运行中的结果进行比较。例如,您可能观察到身份哈希码是延迟分配的 - 因此,无论您首先为哪个对象请求哈希码,都会在您的特定系统上获得 31866429,下一个获得 16795905。

    如果您在单次运行中反转顺序,您应该会看到一致的结果:

    System.out.println(System.identityHashCode(sher));
    System.out.println(sher1.hashCode());
    System.out.println(System.identityHashCode(sher1));
    System.out.println(sher.hashCode());
    

    这里输出的第 1 行和第 4 行应该具有相同的值,第 2 行和第 3 行应该具有相同的值。

    【讨论】:

    • 我对同一程序的不同执行结果感到惊讶!感谢您的澄清。
    【解决方案2】:

    目前还不清楚您要做什么。给定的对象引用具有给定的 hashCode。这将为identityHashCode 和未覆盖的hashCode 返回。但是,您有两个不同的对象引用。因此,如果 Object.hashCode 未被覆盖,这些将具有不同的 hashCode。

    您在运行之间看到相同的 hashCode 是机会。如果您这样做的时间足够长,并且经过足够多的 JVM 重新启动,情况就不会如此。

    您确实以相同的顺序看到相同的 hashCode 的事实是因为 hashCode 仅在您第一次调用 hashCode 时分配给对象引用,而不是在创建对象时。因此,第一次调用 hashCode 会在两次运行中获取第一个代码,无论它是哪个对象。

    试试

      // both lines output the same hashCode for sher
      System.out.println(System.identityHashCode(sher));
      System.out.println(sher.hashCode());
    

      // both lines output the same hashCode for sher1
      System.out.println(System.identityHashCode(sher1));
      System.out.println(sher1.hashCode());
    

    如果将所有 4 行并排放置,您将看到两条相同的线,然后还有两条与第一对不同的相同线。

    如果您现在想为 hashCode()identityHashCode 返回不同的 hashCode,请添加一个字段并在您的覆盖中返回一个 hashCode:

    public class SherlockGCD {
      private int id;
      public SherlockGD(int id) { this.id = id; }
      public int hashCode()
      {
        return id;
      }
      ...
    

    【讨论】:

    • 我说输出应该是反向的,因为两个对象都不一样!!
    • 您的意思是在同一程序的不同运行之间?这不太可能。您将看到如何生成 hashCodes 的人工制品。对于某些 JVM,它们基于内存地址。因此,您的第一个对象和第二个对象恰好在您查看的运行之间采用相同的内存(实际上是内部,而不是内存)地址。再等一会儿,它们可能会完全改变。
    • 这就是我感到困惑的地方。然后我认为 jvm 将从某个特定地址开始,它将第一个对象存储在该地址,因此不同的执行会给出相同的结果。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-10
    • 1970-01-01
    • 2012-11-26
    • 1970-01-01
    • 2013-02-20
    • 2010-12-28
    相关资源
    最近更新 更多