如果你的对象是不可变的,它就不能改变它的状态,因此它的哈希码也不能改变。这使您可以在需要时计算该值并缓存该值,因为它始终保持不变。实际上,hasCode
基于可变状态实现您自己的函数是一个非常糟糕的主意,因为例如HashMap
假设哈希不能改变,如果它改变它就会中断。
延迟初始化的好处是哈希码计算被延迟到需要时。许多对象根本不需要它,因此您可以节省一些计算。特别是昂贵的散列计算,如 on long String
s 会从中受益。
class FinalObject {
private final int a, b;
public FinalObject(int value1, int value2) {
a = value1;
b = value2;
}
// not calculated at the beginning - lazy once required
private int hashCode;
@Override
public int hashCode() {
int h = hashCode; // read
if (h == 0) {
h = a + b; // calculation
hashCode = h; // write
}
return h; // return local variable instead of second read
}
}
编辑:正如@assylias 所指出的,使用非同步/非易失性代码只有在只有 1 次读取时才能保证工作,hashCode
因为即使第一次读取已经看到不同的值,该字段的每次连续读取都可能返回 0。以上版本解决了这个问题。
Edit2:替换为更明显的版本,代码略少但字节码大致相当
public int hashCode() {
int h = hashCode; // only read
return h != 0 ? h : (hashCode = a + b);
// ^- just a (racy) write to hashCode, no read
}