Object.hashCode
或System.identityHashCode
时会生成一个随机数并存储在对象标头中。随后对Object.hashCode
或System.identityHashCode
的调用只是从标头中提取此值。默认情况下,它与对象内容或对象位置没有任何关系,只是一个随机数。此行为由-XX:hashCode=n
HotSpot JVM选项控制,该选项有以下可能的值:
1
(用于测试/调试目的)-XX:hashCode=4
,hashCode也不总是指向对象地址。对象可能稍后移动,但hashCode仍将保持不变。而且,对象地址分布不均(如果您的应用程序使用的内存不多,则大多数对象将靠近彼此),因此如果使用此选项,则可能会导致不平衡的哈希表。-XX:hashCode=n
是一个实验性功能,需要先启用它,然后使用上述标志,因此组合的vm标志为:-XX:+UnlockExperimentalVMOptions -XX:hashCode=4
,在java-11中进行了测试。 - dkb如果你没有覆盖(override)hashCode()方法,通常它会返回对象在内存中的地址。
从1得知:
尽可能地讲,由Object类定义的hashCode方法返回不同的整数。 (通常这是通过将对象的内部地址转换为一个整数来实现的,但Java编程语言并不要求使用这个实现技巧)
1 http://java.sun.com/javase/6/docs/api/java/lang/Object.html#hashCode
hashCode
“可能或可能不会在某个时间点被实现为对象内存地址的某些函数”,然后完全删除了地址的提及,消除了任何混淆的源头。案件结束。 - HolgerhashCode()
的实现因类而异,但 hashCode()
的契约却非常明确和清晰地在 Javadoc 中规定:
返回对象的哈希码值。此方法支持哈希表(例如 java.util.Hashtable)等使用。
hashCode
的通用契约如下:
- 在 Java 应用程序的同一次执行过程中,只要不修改用于对象相等比较的信息,多次调用 hashCode 方法必须始终返回相同的整数。这个整数不需要在应用程序的一个执行过程中保持一致到另一个执行过程。
- 如果根据 equals(Object) 方法两个对象相等,则对这两个对象中的每个对象调用 hashCode 方法都必须产生相同的整数结果。
- 虽然不要求如果两个对象根据 equals(java.lang.Object) 方法是不相等的,那么对这两个对象中的每个对象调用 hashCode 方法必须产生不同的整数结果,但是程序员应该意识到,为不相等对象生成不同的整数结果可能会提高哈希表的性能。
尽可能实际,由 Object 类定义的 hashCode 方法确实为不同的对象返回不同的整数。(这通常是通过将对象的内部地址转换为整数来实现的,但 JavaTM 编程语言并不要求此实现技术。)
hashCode()
方法与equals()
方法密切相关,如果你要覆盖equals()
方法,那么也应该覆盖hashCode()
方法。
if (obj.hash() == 0) { obj.set_hash(generate_new_hash()); } return obj.hash();
如果一个类重写了equals方法,那么它必须也重写hashCode方法。否则会违反Object.hashCode的通用契约,从而导致你的类无法与所有基于哈希的集合(包括HashMap、HashSet和Hashtable)一起正常运行。
哈希码对于将对象存储在集合中(例如哈希集)非常有用。通过允许对象定义一个唯一的哈希码,它使得哈希集算法能够有效地工作。
Object本身使用内存中的对象地址,这是非常独特的,但如果两个不同的对象(例如两个相同的字符串)应该被视为相同,即使它们在内存中重复,这种方法可能并不是很有用。
这并不是一个答案,而是对我之前评论的补充
对象的内部地址在JVM中不能保证不变,因为垃圾回收器可能会在堆压缩期间将其移动。
我尝试做了这样一件事:
public static void main(String[] args) {
final Object object = new Object();
while (true) {
int hash = object.hashCode();
int x = 0;
Runtime r = Runtime.getRuntime();
List<Object> list = new LinkedList<Object>();
while (r.freeMemory() / (double) r.totalMemory() > 0.3) {
Object p = new Object();
list.add(p);
x += object.hashCode();//ensure optimizer or JIT won't remove this
}
System.out.println(x);
list.clear();
r.gc();
if (object.hashCode() != hash) {
System.out.println("Voila!");
break;
}
}
}
但是哈希码确实没有改变...有人能告诉我Sun的JDK实际上如何实现Obect.hashcode吗?