class Employee {
String name;
Employee(String name) {
this.name = name;
}
// hashCode method is not overridden
}
public class HashCodeConfusion {
public static void main(String[] args) {
Employee emp = new Employee("ABC");
Employee emp1 = new Employee("ABC");
if (emp == emp1) {
System.out.println("Employee Same reference");
} else {
System.out.println("Employee Different reference");
}
if (emp.hashCode() == emp1.hashCode()) {
System.out.println("Employee Same hash code");
} else {
System.out.println("Employee Different hash code");
}
// -----------------------------------
String str = new String("ABC");
String str1 = new String("ABC");
if (str == str1) {
System.out.println("String Same reference");
} else {
System.out.println("String Different reference");
}
if (str.hashCode() == str1.hashCode()) {
System.out.println("String Same hash code");
} else {
System.out.println("String Different hash code");
}
}
}
问题/混乱:对象类的默认哈希码似乎正在考虑对象引用,而不仅仅是内容,为什么具有相同名称的员工类对象会带有不同的哈希代码?如果仅基于内容的对象类的默认实现具有某些哈希算法,那么只要我的等价范式与位兼容性一致,就不需要覆盖哈希码方法。
。什么要清除这种混乱?
默认hashcode()不是基于参考的,也不基于系统中的任何地址。它是存储在标题中的随机生成的数字。它可以这样做,以便可以在不更改hashCode()的情况下移动对象,并且哈希码是合理的随机。
注意:
- 次要GC后,伊甸园空间为空,而创建的第一个对象始终处于同一地址。它没有相同的哈希码。
- 默认情况下在8字节边界上创建对象,因此下三位可以是所有000,这对hashcode没有用。如果您使用压缩的OOPS,则可能不会存储较低的位,但仍然不是很随机。
- 使用
Unsafe
,您可以读取甚至覆盖存储的标签。在OracleJVM/OpenJDK上,从对象的开头存储了1个字节。 - 用于存储HashCode的位也用于baised锁定。一旦您获得了一个对象的内置哈希码,它就不会使用偏置锁定。
- 您可以使用
IdentityMap
使用的System.identityHashCode(x)
获得任何对象的系统哈希码。