System.identityHashCode()对原语的行为

ele*_*ect 0 java primitive hashcode kotlin

jvm imgui中,我正在使用

System.identityHashCode(i++)

哪里

var i = 0

为每个帧始终为给定对象生成一个常数id(因此
可以对其进行跟踪)

但是,一个用户案例只是告诉我,这仅对中的值有效[0, 125]

尝试调试并查找错误,我结束了这段简短的代码测试:

    var i = 0
    val A = Array(256, { System.identityHashCode(i++) })
    i = 0
    val B = Array(256, { System.identityHashCode(i++) })
    repeat(256) {
        if (A[it] != B[it])
            println("[$it] different, A ${A[it]}, B ${B[it]}")
    }
Run Code Online (Sandbox Code Playgroud)

还有:

  • 字节(完全正常工作,对于所有256个值,A == B)
  • 短裤(不能从128开始工作)
  • 整数(从128开始无效)
  • 多头(不能从128开始工作)
  • 浮动(完全不起作用)
  • 加倍(根本不起作用)

这是为什么?

我是否可以安全地假设这种行为在其他平台上也能保持一致?

Gra*_*ray 5

但是,一个用户案例只是告诉我,这仅对[0,125]中的值有效

System.identityHashCode(Object)采用Object非原语,这意味着您将i++被自动装箱为Integer(或Long或...)。对象具有相同身份哈希码的唯一时间是(但并非总是)当它们是同一对象时。碰巧的是,JVM Integer为了优化目的而缓存了少量的s,这意味着0到127值的标识哈希码是相同的。

自动装箱发生时,编译器会生成的调用Integer.valueOf(int)。如果我们看一下`valueOf(...)的代码,我们会看到:

if (i >= IntegerCache.low && i <= IntegerCache.high)
    return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
Run Code Online (Sandbox Code Playgroud)

因此,存在一个低缓存范围和一个高缓存范围,您将从中获得一个在JVM启动时生成的缓存常量对象。有JVM参数会影响数字高速缓存的大小。因此127必须在您的JVM的缓存范围内,而128以上的版本不在。

// both of the 100 values gets auto-boxed to the same Integer object
System.identityHashCode(100) == System.identityHashCode(100)
Run Code Online (Sandbox Code Playgroud)

这基本上等效于比较同一对象的哈希码:

Integer i = new Integer(100);
System.identityHashCode(i) == System.identityHashCode(i)
Run Code Online (Sandbox Code Playgroud)

一旦超过了初始缓存的Integer值集并指定了更大的int值,新的Integer对象将在自动装箱后创建,因此(很可能)标识哈希码不再相等。

// by default, each of these 1000000 values gets auto-boxed to a different object
System.identityHashCode(1000000) != System.identityHashCode(1000000)
Run Code Online (Sandbox Code Playgroud)

这基本上等效于实例化2个不同的整数,并期望它们的哈希码相同:

Integer i1 = new Integer(1000000);
Integer i2 = new Integer(1000000);
System.identityHashCode(i1) != System.identityHashCode(i2)
Run Code Online (Sandbox Code Playgroud)

请注意,System.identityHashCode(...)不会返回唯一值,因此,当查看不同的对象时,它们有可能(尽管不太可能)生成相同的值。