为什么两个具有相同值的原始双精度具有两个不同的identityHashCode?

问题描述 投票:2回答:4

我了解到所有具有相同值的基元都具有相同的identityHashCode所以,我想得到一些原始的identityHashCode。所以当我尝试使用相同值的2个双打时,我给了不同的identityHashCode我做了以下:

int xInt=5;
int yInt=5;

System.out.println(System.identityHashCode(xInt));//output:1867083167
System.out.println(System.identityHashCode(yInt));//output:1867083167

double double1=5;
double double2=5;


System.out.println(System.identityHashCode(double1));//output:1915910607

System.out.println(System.identityHashCode(double2));//output:1284720968

两个具有相同值的整数具有相同的identityHashCode但两个具有相同值的双精度具有不同的identityHashCode,为什么呢?

java double
4个回答
7
投票

你的代码正在装箱原始值。 (原始值本身没有标识哈希码,因为这只是与对象相关的概念。)您的代码等同于:

int xInt=5;
int yInt=5;

Integer xInteger = xInt;
Integer yInteger = yInt;

System.out.println(System.identityHashCode(xInteger));
System.out.println(System.identityHashCode(yInteger));

double double1=5;
double double2=5;

Double boxedDouble1 = double1;
Double boxedDouble2 = double2;

System.out.println(System.identityHashCode(boxedDouble1));
System.out.println(System.identityHashCode(boxedDouble2));

现在,如果你比较参考本身,你会看到xInteger == yInteger是真的,但是boxedDouble1 == boxedDouble2是假的......所以identityHashCode正确地表示了这种关系。

你的盒装整数引用引用同一个对象的原因是boxed integral types within a particular range are cached

如果被装箱的值是评估boolean,char,short,int或long类型的常量表达式(第15.28节)的结果,结果为true,false,则为'\ u0000'到''范围内的字符\ u007f'包含,或-128到127(含)范围内的整数,然后让a和b为p的任意两次装箱转换的结果。 a == b总是如此。

在实践中,范围实际上可能更大,并且实现也可以缓存盒装双打,但我还没有看到这种情况发生。


0
投票

我了解到所有具有相同值的基元具有相同的identityHashCode

这不可能是真的,因为根据定义,原语不是对象,因此首先没有标识哈希码。

当你调用System.identityHashCode()时,参数被装箱为Integer或Double。

整数拳击使用a cache for the frequently used integers(默认情况下从-128到127)。双拳并非如此。

尝试使用大型int,你也会得到不同的结果。


0
投票

这里有一个拳击问题 - 你无法将原始数据类型与qazxsw poi进行比较,因为它使用qazxsw poi作为参数。

返回与默认方法hashCode()返回的给定对象相同的哈希码

但当然identityHashCodeObject不同。


0
投票

我了解到所有具有相同值的基元具有相同的identityHashCode。

那里至少存在两种​​误解。首先,原语根本没有哈希码或身份哈希码。它是对象,例如通过自动装箱原始值获得的包装器对象。

其次,总体思路完全错误,正如您自己的实验所证明的那样。如果您提供一个原语作为double的参数,那么它将自动装入相应包装类的实例中,并返回结果对象的标识哈希码。对象的标识哈希码在其生命周期中是该对象的唯一特征,并且与其状态无关。同时存在的两个对象不具有相同的标识哈希码。那么,更有趣的是,你不是为自动装箱的Doubles获得不同的身份哈希码,而是为自动装箱的小整数获得相同的身份哈希码。

实际上,这表明Java为小整数值维护了System.identityHashCode()对象的缓存。它在覆盖范围内的自动装箱值时以及处理这些值的显式double调用时使用这些值。因此,在您的示例中,每次自动装订整数5时都会获得相同的对象,并且您会看到相同的标识哈希码。如果您使用了足够大的值,那么您将看不到相同的效果。

Java不会为值为5.0的Integers执行此类缓存。

另一方面,也许你只是误解了这一课。表示相同基元类型和值的不同包装器对象不具有相同的标识哈希代码,但它们具有相同(常规)哈希代码,因为对于包装类,它们由它们表示的原始值确定。因此,将代码的结果与此结果进行比较:

Integer.valueOf()
© www.soinside.com 2019 - 2024. All rights reserved.