Java 中原语的哈希码计算给出常量值的不同结果[重复]

问题描述 投票:0回答:0

TL;博士

在 Java 中,执行

int i = 327; // arbitrary int >127

int hashcode1 = System.identityHashCode(i);
int hashcode2 = System.identityHashCode(i);

产生两个不同的值 (

hashcode1 != hashcode2
),如果
i
大于 127。为什么会发生这种情况?

详细的问题和可重现的例子

Java 哈希码简介

本节包含有关哈希码的实现和使用的信息。随意跳过它。

在Java中,对象的hashcode可以通过调用任何实例化对象的

Object#hashCode()
获得。根据 docs,方法
System#identityHashCode(Object)
返回与直接在作为参数传递的对象上调用
#hashCode()
相同的方法。根据定义,如果(但不仅限于)对象相同(取决于实现,语义相等就足够),则此哈希码必须相等,这意味着相同的对象返回相同的哈希码。

根据this thread/answer,在初始生成之后,哈希码与对象一起存储在堆中的某个地方。

不像

#hashCode()
System#identityHashCode(Object)
也可以接受基元(例如
int
double
)作为输入参数。我不知道哈希码是否也可以与原语一起存储在 RAM 中,但我猜不会。

意外行为的描述

奇怪的是,当将

int
变量传递给
#identityHashCode(...)
时,低于并包括
127
的值会产生一个常量哈希码。但是,对于更大的值,重复执行所述方法总是会返回不同的哈希码(至少在我的机器上是这样;))。此外,这适用于任何
double
值(我没有广泛测试 double 或 float)。

像任何其他对象一样,像

Integer
这样的包装类对象似乎不受影响。

可重现的独立示例

注释:

ObjectHolder
类只是为了更容易测试的样板。

public class PrimitiveHashcodes
{
    public static void main(String[] args)
    {
        // creating arbitrary non-null object
        Object object = new JPanel(new GridBagLayout(), false);

        ObjectHolder objectHolder = new ObjectHolder(object, 127, 128, 'B', 3.14d, new Integer(128));
        objectHolder.test();
        objectHolder.test();
        objectHolder.test();
        objectHolder.test();
    }
}

class ObjectHolder
{

    Object obj;
    int intSmall;
    int intBig;
    char character;
    double db;
    Integer wrapped;

    public ObjectHolder(Object obj, int iSmall, int iBig, char character, double db, Integer wrapped)
    {
        this.obj = obj;
        this.intSmall = iSmall;
        this.intBig = iBig;
        this.character = character;
        this.db = db;
        this.wrapped = wrapped;

        System.out.println(" Object  | IntSmall |  IntBig  |   char   |  double  | wrapped");
        System.out.println("---------|----------|----------|----------|----------|---------");
    }

    public void test()
    {
        System.out.printf("%08x | %08x | %08x | %08x | %08x | %08x%n", System.identityHashCode(obj),
                System.identityHashCode(this.intSmall), System.identityHashCode(this.intBig),
                System.identityHashCode(this.character), System.identityHashCode(this.db),
                System.identityHashCode(wrapped));
    }
}

示例输出(格式为表格):

对象 小号 IntBig 包裹
34a245ab 7cc355be 6e8cf4c6 12edcd21 34c45dca 52cc8049
34a245ab 7cc355be 0133314b 12edcd21 0b1bc7ed 52cc8049
34a245ab 7cc355be 7cd84586 12edcd21 030dae81 52cc8049
34a245ab 7cc355be 1b2c6ec2 12edcd21 4edde6e5 52cc8049
- - - - - -
常量 常量 任意 常量 任意 常量

如何解释这种现象?首先如何计算原语的哈希码?

java jvm hashcode
© www.soinside.com 2019 - 2024. All rights reserved.