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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4930781/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 08:39:35  来源:igfitidea点击:

How do hashCode() and identityHashCode() work at the back end?

javaobjecthashcode

提问by Himanshu

How do Object.hashCode()and System.identityHashCode()work at the back end? Does identityHashCode()return the reference of the object? Does hashCode()depend on the ? of the object ? == operator how to work in back end.

如何做Object.hashCode()System.identityHashCode()工作在后端?是否identityHashCode()返回对象的引用?不hashCode()取决于?的对象?== 运算符如何在后端工作。

What is the difference between hashCode()and identityHashCode()?

hashCode()和 和有什么不一样identityHashCode()

回答by Stephen C

How do Object.hashCode() and System.identityHashCode() work at the back end?

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

Assuming that it hasn't been overridden, the Object.hashCode()method simply calls System.identityHashCode(this).

假设它没有被覆盖,该Object.hashCode()方法只是调用System.identityHashCode(this).

The exact behavior of System.identityHashCode(Object)depends on the JVM implementation. (The actual implementation on recent Hotspot JVMs is rather clever, but I digress.)

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

Does identityHashCode()return the reference of the object?

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

No. It returns an int, and an intcannot hold a reference.

不。它返回一个int,并且一个int不能保存引用。

That integer returned by identityHashCodemay be related to the (a) machine address for the object, or it may not be1. The value returned by identityHashCode()is guaranteed not to changefor the lifetime of the object. This means that if the GC relocates an object (after an identityHashCode()call) then it cannot use the new object address as the identity hashcode.

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

Does hashCode() depend on the ?of the object ? ==operator how to work in back end.

hashCode() 是否取决于?对象? ==运算符的后端如何工作。

This doesn't make sense. There is no ? ==or ?==operator in Java.

这没有意义。Java 中没有? ==or?==运算符。

What is the difference between hashCode() and identityHashCode()?

hashCode() 和 identityHashCode() 有什么区别?

This is partly explained above. Other differences include:

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

  • The hashcode()method is a non-final instance method, and should be overridden in any class where the equals(Object)is overridden. By contrast, identityHashCode(Object)is a staticmethod and therefore cannot be overridden.

  • The identityHashCode(Object)method gives you a identifier for an object which can (in theory) be used for other things than hashing and hash tables. (Unfortunately, it is not a uniqueidentifier, but it isguaranteed to never change for the lifetime of the object.)

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

  • identityHashCode(Object)方法为您提供了一个对象的标识符,该标识符(理论上)可以用于除散列和散列表之外的其他事情。(不幸的是,它不是一个独特的标识符,但保证为对象的生命周期永远不会改变。)



1 - For current generation JVMs, it is not related to the memory address at all. See @bestsss's answer.

1 - 对于当前一代 JVM,它与内存地址完全无关。请参阅@bestsss 的回答。

回答by bestsss

identityHashCode() works like that (and as of now it has nothing do to w/ the address, esp. since the addresses are 64bits long, ok aligned, so 61)

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

Checks if the there is already generated one, if so returns it. You can assume there is a place in the object header for that int;

检查是否已经生成了一个,如果是则返回它。您可以假设对象标题中有一个位置int

otherwise: generates a random number (iirc twisterMarsaglia shift-xoralgorithm), every native thread has its own seed, so no shared info. CAS the identityHashCodefield in the object header to update w/ the newly generated number. if CAS success returns the value, if not - the field already contains a generated identityHashCode.

否则:生成一个随机数(iirc twiner Marsaglia shift-xoralgorithm),每个本地线程都有自己的种子,所以没有共享信息。CASidentityHashCode对象标头中的字段以更新新生成的数字。如果 CAS 成功返回值,否则 - 该字段已包含生成的identityHashCode.

you can see the rest of the replies about overriding hashcode.

你可以看到其他关于覆盖哈希码的回复。

bottom line: if the javadoc still states anything about addresses and identityHashCode, someone needs to update it.

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

回答by templatetypedef

This is pretty much implementation specific. The only guarantee you get is

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

As much as is reasonably practical, the hashCodemethod defined by class Objectdoes return distinct integers for distinct objects. (This is typically implemented by converting the internal address of the object into an integer, but this implementation technique is not required by the JavaTMprogramming language.)

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

(From the Java 1.6 JavaDoc)

(来自 Java 1.6 JavaDoc)

In theory, this means that the values could be determined arbitrarily and could even be zero for every object. In practice, it's probably something derived from the address of the object. Of course, you have to be careful about this. The JVM can relocate objects if it thinks it's a good idea during a garbage collection, so it's not going to be "just" the memory address. It could be drawn from a global counter, or a hash of the original object's location, or from a random number generator, etc.

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

回答by Vishrant

identityHashCode

public static int identityHashCode(Object x)

Returns the same hash code for the given object as would be returned by the default method hashCode(), whether or not the given object's class overrides hashCode(). The hash code for the null reference is zero.

身份哈希码

public static int identityHashCode(Object x)

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

See [Java docs]

请参阅 [ Java 文档]

So if someone has overridden hashCode()method in its class but still want the default hashCode()value which would have been returned by ObjecthashCode()then use System.identityHashCode()

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

So, hashCode()internally calls System.identityHashCode()as long as you are not overriding it in you class, if you override hashCode() it will call your implementation.

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

回答by Hitesh Ghuge

Lots of answers given above, just need to add some points.

上面给出了很多答案,只需要补充一些要点。

When we say obj.hashCode()the content of the obj is considered, on the other hand in System.identityHashCode(obj)the content are not taken in consideration, thus identityHashCodefor two different String, int(with same value) will be the different but Hashcodewill be the same.

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

In case of Stringto get identityHashCodestring pool plays important role, example

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

here s1and s3pointing same ref therefore identityHashCodefor s1 and s3is always same and s2will be different.

heres1s3指向相同的 ref 因此identityHashCodefors1 and s3总是相同的,并且s2会有所不同。

Same for intalso, IntegerCacheplays the important role to get the identityHashCode

同样为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