Java hashCode()和identityHashCode()在后端如何工作?

Java hashCode()和identityHashCode()在后端如何工作?,java,object,hashcode,Java,Object,Hashcode,如何在后端执行和工作?identityHashCode()是否返回对象的引用?hashCode()是否取决于对象的内容或地址 hashCode()和identityHashCode()之间的区别是什么?这几乎是特定于实现的。你得到的唯一保证是 只要合理可行,类Object定义的hashCode方法会为不同的对象返回不同的整数。(这通常通过将对象的内部地址转换为整数来实现,但JavaTM编程语言不需要这种实现技术。) (来自Java1.6Javadoc) 理论上,这意味着可以任意确定值,甚至每个对

如何在后端执行和工作?
identityHashCode()
是否返回对象的引用?
hashCode()
是否取决于对象的内容或地址


hashCode()
identityHashCode()
之间的区别是什么?

这几乎是特定于实现的。你得到的唯一保证是

只要合理可行,类
Object
定义的
hashCode
方法会为不同的对象返回不同的整数。(这通常通过将对象的内部地址转换为整数来实现,但JavaTM编程语言不需要这种实现技术。)

(来自Java1.6Javadoc)

理论上,这意味着可以任意确定值,甚至每个对象的值都可以为零。实际上,它可能是从对象的地址派生出来的。当然,你必须小心。如果JVM认为在垃圾收集过程中重新定位对象是一个好主意,那么它可以重新定位对象,因此它不会“仅仅”是内存地址。它可以从全局计数器、原始对象位置的散列或随机数生成器等中提取

Object.hashCode()和System.identityHashCode()在后端如何工作

假设它没有被重写,
对象.hashCode()
方法只调用
System.identityHashCode(this)

System.identityHashCode(对象)
的确切行为取决于JVM实现。(最近热点JVM上的实际实现相当聪明,但我离题了。)

identityHashCode()
是否返回对象的引用

否。它返回一个
int
,而
int
不能保存引用

identityHashCode
返回的整数可能与对象的(a)机器地址有关,也可能不是1。
identityHashCode()
返回的值保证在对象的生存期内不会更改。这意味着如果GC重新定位一个对象(在调用
identityHashCode()
之后),那么它就不能使用新的对象地址作为标识哈希代码

hashCode()是否依赖于对象的
==操作员如何在后端工作

这没有道理。没有
==或
?==
运算符

hashCode()和identityHashCode()之间有什么区别

以上部分解释了这一点。其他差异包括:

  • hashcode()
    方法是一个非最终实例方法,应该在重写
    equals(Object)
    的任何类中重写。相比之下,
    identityHashCode(Object)
    是一种
    静态方法,因此不能被重写

  • identityHashCode(Object)
    方法为对象提供一个标识符,该标识符(理论上)可用于哈希表和哈希表以外的其他用途。(不幸的是,它不是唯一标识符,但保证在对象的生命周期内不会更改。)


1-对于当前一代JVM,它与内存地址根本不相关。请参阅@bestsss的答案。

identityHashCode()
就是这样工作的(到目前为止,它与地址无关,特别是因为地址是64位长的,可以对齐,所以是61位):

检查是否已生成一个,如果已生成,则返回它。您可以假设在对象头中有一个位置用于该
int

否则:生成一个随机数(算法)。每个本机线程都有自己的种子,因此没有共享信息。 CAS对象标题中的
identityHashCode
字段以更新新生成的编号。如果CAS成功,则返回值。如果不是,则该字段已包含生成的
identityHashCode

您可以看到关于覆盖哈希代码的其余回复

底线: 如果JavaDoc仍然声明关于地址和
identityHashCode
的任何内容,则需要有人对其进行更新

识别码 公共静态int-identityHashCode(对象x)

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

见[]

因此,如果有人在其类中重写了
hashCode()
方法,但仍然需要对象
hashCode()
返回的默认值,则使用
System.identityHashCode()


因此,
hashCode()
内部调用
System.identityHashCode()
只要您没有在类中重写它,如果您重写hashCode(),它将调用您的实现。

上面给出了很多答案,只需要添加一些要点

另一方面,当我们说
obj.hashCode()
时,会考虑obj的内容 在
System.identityHashCode(obj)
中,不考虑内容,因此
identityHashCode
对于两个不同的
字符串
int
(具有相同的值)将不同,但
Hashcode
将相同

String
获取
identityHashCode
的情况下,字符串池扮演着重要的角色,例如

    Object s1 = "abcd";
    Object s2 = new String("abcd");
    Object s3 = "abcd";
    System.out.println("identityHashCode : " + System.identityHashCode(s1) + " HashCode : " + s1.hashCode());
    System.out.println("identityHashCode : " + System.identityHashCode(s2) + " HashCode : " + s2.hashCode());
    System.out.println("identityHashCode : " + System.identityHashCode(s3) + " HashCode : " + s3.hashCode());

    //output:
    identityHashCode : 2018699554 HashCode : 2987074
    identityHashCode : 1311053135 HashCode : 2987074
    identityHashCode : 2018699554 HashCode : 2987074
此处
s1
s3
指向相同的参考,因此
s1和s3
identityHashCode
始终相同,
s2
将不同

int
相同,
IntegerCache
在获取
identityHashCode

    Object s1 = 5;
    Object s2 = new Integer(5);
    Object s3 = 5;
    System.out.println("identityHashCode : " + System.identityHashCode(s1) + " HashCode : " + s1.hashCode());
    System.out.println("identityHashCode : " + System.identityHashCode(s2) + " HashCode : " + s2.hashCode());
    System.out.println("identityHashCode : " + System.identityHashCode(s3) + " HashCode : " + s3.hashCode());

    //Output
    identityHashCode : 2018699554 HashCode : 5
    identityHashCode : 1311053135 HashCode : 5
    identityHashCode : 2018699554 HashCode : 5
你说得对,我一定有