我试图理解 Java 对象的 hashCode() 方法,并看到了 Java 对象的 hashCode() 方法的以下代码:
package java.lang;
public class Object {
// Some more code
public native int hashCode();
// Some other code
}
现在,我们知道,如果我们创建一个类,它会隐式扩展 Object 类,为此我编写了一个示例:
package com.example.entity;
public class FirstClass {
private int id;
private String name;
// getters and setters
}
因此,这个类即:FirstClass
将隐式扩展 Object
类。
主类:
package com.example.app.main;
import com.example.entity.FirstClass;
public class MainApp {
public static void main(String[] args) {
FirstClass fs = new FirstClass();
fs.setId(1);
fs.setName("TEST");
System.out.println("The hasCode for object fs is " + fs.hashCode());
}
}
由于 FirstClass
隐式扩展 Object
类,因此它将具有 Object
类的 hashCode()
方法.
我在 FirstClass
对象上调用了 hashCode()
,并且由于我没有重写 hashCode()
,理论上它应该调用 Object
类的 hashCode()
。
我的疑问是:
由于Object类没有任何实现,它如何计算任何对象的哈希码?
就我而言,当我运行该程序时,它返回的哈希代码是 366712642。
谁能帮我理解这个?
最佳答案
尽管这里有一些答案指出默认实现是基于“内存”的,但这显然是错误的。现在已经很多年没有出现这种情况了。
在java-8下,你可以这样做:
java -XX:+PrintFlagsFinal | grep hashCode
获取所使用的确切算法(5
为默认值)。
0 == Lehmer random number generator,
1 == "somehow" based on memory address
2 == always 1
3 == increment counter
4 == memory based again ("somehow")
5 == read below
默认情况下(5
),它使用Marsaglia XOR-Shift算法,与内存无关。
这并不难证明,如果你这样做的话:
System.out.println(new Object().hashCode());
在新的虚拟机中始终多次 - 您将获得相同的值,因此 Marsaglia XOR-Shift 从种子开始(始终相同,除非某些其他代码不会改变它)并从此开始工作。
但是,即使您切换到一些基于内存的 hashCode,并且对象可能会四处移动(垃圾收集器调用),您如何确保在 GC 移动该对象之后采用相同的 hashCode ?提示:indentityHashCode 和 Object header 。
关于java - Java 对象的默认 hashCode() 实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49172698/