我了解到所有具有相同值的图元都具有相同的identityHashCode
,因此,我希望获得identityHashCode
的一些图元。因此,当我尝试使用具有相同值的2个双精度数时,会给出不同的{{1} }我做到了:
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
,为什么?
答案 0 :(得分: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:
如果要装箱的值p是对boolean,char,short,int或long类型的常量表达式(第15.28节)求值的结果,并且结果为true,false,则是'\ u0000范围内的字符'到'\ u007f'(含)或-128至127(含)范围内的整数,则令a和b为p的任何两次装箱转换的结果。通常= = b。
实际上,范围可以更大,并且实现可以缓存盒装功能也可以加倍,但是我还没有看到这种情况。
答案 1 :(得分:0)
我了解到所有具有相同值的原语都具有相同的identityHashCode
那是不对的,因为根据定义,基元不是对象,因此一开始就没有身份哈希码。
调用System.identityHashCode()
时,该参数将以整数或Double形式出现。
并且Integer装箱使用a cache for the frequently used integers(默认为-128到127)。 Double Boxing并非如此。
以较大的整数进行尝试,您也会得到不同的结果。
答案 2 :(得分:0)
这里有一个拳击问题-您无法将原始数据类型与identityHashCode
进行比较,因为它使用Object
作为其参数。
为给定对象返回与将返回的哈希码相同的哈希码 通过默认方法hashCode()
但是,当然double
与Double
不同。
答案 3 :(得分:0)
我了解到所有具有相同值的原语都具有相同的identityHashCode。
至少有两个误解。首先,基元根本没有哈希码或身份哈希码 。是对象,例如通过自动装箱原始值获得的包装对象。
第二,正如您自己的实验所证明的那样,总体思路是错误的。如果您提供原语作为System.identityHashCode()
的参数,则该原语将自动装箱到适当包装类的实例中,并返回结果对象的标识哈希码。对象的身份哈希码是该对象在其生存期内的唯一特征,并且独立于其状态。不能同时存在两个对象具有相同的身份哈希码。那么,更有趣的是,您没有为自动装箱的double
获得不同的身份哈希码,而是为自动装箱的小整数获得了相同身份哈希码。
实际上,这表明Java维护了Integer
对象的高速缓存,以存储较小的整数值。当自动装箱覆盖范围内的值时,以及在处理这些值的显式Integer.valueOf()
调用时,它将使用它们。因此,在您的示例中,每次对整数5进行自动装箱时,都会得到相同的对象,并且看到相同的标识哈希码。如果您使用足够大的值,那么您将不会看到相同的效果。
Java不会对值为{5.0的Double
执行此类缓存。
另一方面,也许您只是误解了这一课。表示相同原始类型和值的不同包装对象没有相同的 identity 哈希码,但 do 却具有相同的(常规)哈希码,因为包装器类由它们表示的原始值确定。因此,将您的代码结果与以下结果进行比较:
System.out.println(Double.valueOf(double1).hashCode());
System.out.println(Double.valueOf(double2).hashCode());