我试图理解Java对象的hashCode(),并看到了Java Object的hashCode()方法的以下代码:
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()
个类&#39}。 hashCode()
方法。
我在FirstClass
对象上调用hashCode()
,因为我没有覆盖Object
,理论上它应该调用hashCode()
类&#39} DELETE
FROM oc
WHERE (a_col = 'G' AND b_col = '11' AND c_col = 'P' AND d_col = 'N')
OR (a_col = 'Z' AND b_col = '1' AND c_col = 'R' AND d_col = 'G')
。
由于Object类没有任何实现,如何计算任何对象的哈希码?
在我的情况下,当我运行程序时,它返回的哈希码是366712642。
任何人都可以帮我理解这个吗?
答案 0 :(得分:10)
尽管这里有一些答案表明默认实现是基于“内存”的,但这是完全错误的。现在很多年情况并非如此。
在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());
多次,在一个新的VM中 - 你将获得相同的值,因此Marsaglia XOR-Shift以种子开始(总是相同的,除非其他一些代码不会改变它)并从中开始工作。 / p>
但即使你切换到一些基于内存的hashCode,而Objects可能会四处移动(垃圾收集器调用),你如何确保在 GC移动了这个对象之后采取相同的hashCode ?提示:indentityHashCode和Object标头。
答案 1 :(得分:4)
你弄错了:
public native int hashCode();
并不意味着没有实现。它只是意味着该方法是在JVM的 native 又名C / C ++部分中实现的。这意味着您无法找到该方法的 Java源代码。但是,只要在某个Object上调用hashCode()
,JVM中的某些代码就会被调用。
正如另一个答案所解释的那样:“默认”实现使用了底层对象的“内存”地址。事情是:使用 java 意味着,不知道“内存地址”。请记住:JVM是用C / C ++编写的 - 真正的内存管理发生在JVM的这些 native 部分。
换句话说:您无法编写告诉您有关对象的“本机内存地址”的Java代码。
但正如Eugene的另一个答案所表明的那样:关于“记忆位置”的哈希已成为过去。
答案 2 :(得分:1)
对象类中Hashcode的默认实现是对象的十六进制内存地址。 JVM调用此实现。
一些有用的链接是:
https://docs.oracle.com/javase/tutorial/java/IandI/objectclass.html https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html