String 与其他 class 对象的 hashCode
The hashCode for String versus other class objects
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");
}
}
}
Question/Confusion:
Object class 的默认 hashCode 似乎考虑了对象引用而不仅仅是内容,否则为什么同名的 employee class 对象会出现不同的哈希码?
如果 Object class 的默认实现有一些仅基于内容的哈希算法,那么只要我的 equals 范式同意按位兼容性,就不需要重写 hashCode 方法。
有什么可以消除这种困惑的吗?
默认的 hashCode() 不基于参考,也不基于系统中的任何地址。它是一个随机生成的数字,存储在 header 中。它这样做是为了在不更改 hashCode() 的情况下移动 object,并且 hashCode 是相当随机的。
注:
- 次要 GC 后,eden space 为空,创建的第一个 object 始终位于同一地址。它没有相同的 hashCode。
- object默认创建在8字节边界上,因此低三位可以全为000,这对hashCode没有用。如果您使用 Compressed Oops,低位可能不会被存储,但仍然不是很随机。
- 使用
Unsafe
您可以读取甚至覆盖存储的哈希码。在 OracleJVM/OpenJDK 上,hashCode 存储在 object. 开头的 1 个字节处
- 用于存储hashCode的位也用于baised locking。一旦你获得了 object 的内置 hashCode,它就不会使用偏向锁定。
- 您可以使用
System.identityHashCode(x)
获取任何 object 的系统 hashCode,这正是 IdentityMap
使用的。
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");
}
}
}
Question/Confusion: Object class 的默认 hashCode 似乎考虑了对象引用而不仅仅是内容,否则为什么同名的 employee class 对象会出现不同的哈希码? 如果 Object class 的默认实现有一些仅基于内容的哈希算法,那么只要我的 equals 范式同意按位兼容性,就不需要重写 hashCode 方法。
有什么可以消除这种困惑的吗?
默认的 hashCode() 不基于参考,也不基于系统中的任何地址。它是一个随机生成的数字,存储在 header 中。它这样做是为了在不更改 hashCode() 的情况下移动 object,并且 hashCode 是相当随机的。
注:
- 次要 GC 后,eden space 为空,创建的第一个 object 始终位于同一地址。它没有相同的 hashCode。
- object默认创建在8字节边界上,因此低三位可以全为000,这对hashCode没有用。如果您使用 Compressed Oops,低位可能不会被存储,但仍然不是很随机。
- 使用
Unsafe
您可以读取甚至覆盖存储的哈希码。在 OracleJVM/OpenJDK 上,hashCode 存储在 object. 开头的 1 个字节处
- 用于存储hashCode的位也用于baised locking。一旦你获得了 object 的内置 hashCode,它就不会使用偏向锁定。
- 您可以使用
System.identityHashCode(x)
获取任何 object 的系统 hashCode,这正是IdentityMap
使用的。