Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/380.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java System.idendityHashCode()和hashCode()方法的内部工作原理是什么?_Java_Hashcode - Fatal编程技术网

Java System.idendityHashCode()和hashCode()方法的内部工作原理是什么?

Java System.idendityHashCode()和hashCode()方法的内部工作原理是什么?,java,hashcode,Java,Hashcode,我读到了System.identityHashCodeObject x。您不能重写它,因为它是静态方法,但我可以重写对象的hashCode方法。javadoc中的System.identityHashCodeObject x也提到了这一点: 为给定对象返回与默认方法hashCode返回的哈希代码相同的哈希代码,无论给定对象的类是否重写 空引用的哈希代码为零 但是,当我通过在println方法中交换对象来运行下面的代码时,我得到了相同的结果 public class SherlockGCD {

我读到了System.identityHashCodeObject x。您不能重写它,因为它是静态方法,但我可以重写对象的hashCode方法。javadoc中的System.identityHashCodeObject x也提到了这一点:

为给定对象返回与默认方法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方法中的对象时输出没有反转呢???

不清楚您要做什么。给定的对象引用具有给定的哈希代码。这将为identityHashCode和非重写hashCode返回。但是,您有两个不同的对象引用。因此,如果未重写Object.hashCode,则这些将具有不同的hashCode

您在两次运行之间看到相同的哈希代码是偶然的。如果这样做的时间足够长,JVM重新启动的时间足够长,情况就不会是这样了

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

试一试

如果将所有4条线放在一起,您将看到两条相同的线,然后是两条与第一对不同的相同线

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

public class SherlockGCD {
  private int id;
  public SherlockGD(int id) { this.id = id; }
  public int hashCode()
  {
    return id;
  }
  ...
但是,当我通过在println方法中交换对象来运行下面的代码时,我得到了相同的结果

您不应该将一次运行中哈希代码的结果与另一次运行中的结果进行比较。例如,您可能已经观察到,标识哈希代码是惰性分配的,因此,在您的特定系统上,您首先请求哈希代码的对象将获得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行应该具有相同的值。

我说输出应该是反向的,因为两个对象都不同!!你是说在同一个程序的不同运行之间?那不太可能。您看到的是如何生成哈希代码的人工制品。对于某些JVM,它们基于内存地址。因此,第一个对象和第二个对象恰好占用了相同的内存,实际上是内部内存,而不是您查看的两次运行之间的内存地址。再等一会儿,它们可能会完全改变。这就是我困惑的地方。然后我认为jvm将从某个特定的地址开始,它将在该地址存储第一个对象,因此不同的执行会产生相同的结果。我对同一程序的不同执行的结果感到惊讶!!谢谢你的澄清。
public class SherlockGCD {
  private int id;
  public SherlockGD(int id) { this.id = id; }
  public int hashCode()
  {
    return id;
  }
  ...
System.out.println(System.identityHashCode(sher));
System.out.println(sher1.hashCode());
System.out.println(System.identityHashCode(sher1));
System.out.println(sher.hashCode());