详解hashCode()和equals()的本质区别和联系
详解hashCode()和equals()的本质区别和联系 在 Java 中,hashCode() 和 equals() 是两个非常重要的方法,它们都是从 Object 类继承来的。了解这两个方法的本质区别和联系对于 Java 开发者来说至关重要。 equals() 方法 equals() 方法是 Object 类提供的一种方法,用于比较两个对象是否相等。从 Object 类的源代码中可以看到,equals() 方法的实现非常简单,仅仅是比较两个对象的引用是否相同。因此,如果我们直接使用 Object 类的 equals() 方法来比较两个对象,结果将是比较它们的内存地址是否相同,而不是比较它们的逻辑值是否相同。 例如,下面的代码将返回 false,因为 s1 和 s2 虽然具有相同的值,但是它们是不同的对象: String s1 = new String("kvill"); String s2 = new String("kvill"); System.out.println(s1.equals(s2)); // 输出 false 因此,我们需要重写 equals() 方法,以便比较两个对象的逻辑值是否相同。在重写 equals() 方法时,需要遵守通用约定,包括: 1. 自反性:对于任意的引用值 x,x.equals(x) 一定为 true。 2. 对称性:对于任意的引用值 x 和 y,当 x.equals(y) 返回 true 时,y.equals(x) 也一定返回 true。 3. 传递性:对于任意的引用值 x、y 和 z,如果 x.equals(y) 返回 true,并且 y.equals(z) 也返回 true,那么 x.equals(z) 也一定返回 true。 4. 一致性:对于任意的引用值 x 和 y,如果用于 equals 比较的对象信息没有被修改,多次调用 x.equals(y) 要么一致地返回 true,要么一致地返回 false。 5. 非空性:对于任意的非空引用值 x,x.equals(null) 一定返回 false。 hashCode() 方法 hashCode() 方法也是从 Object 类继承来的,该方法返回该对象的哈希码值,该值通常是一个由该对象的内部地址转换而来的整数。hashCode() 方法的主要目的是为了提高哈希表(例如 java.util.Hashtable 提供的哈希表)的性能。 需要注意的是,在每个重写了 equals 方法的类中,你必须也要重写 hashCode 方法。如果不这样做的话,就会违反 Object.hashCode 的通用约定,从而导致该类无法与所有基于散列值(hash)的集合类结合在一起正常运行。 hashCode() 方法的返回值和 equals() 方法的关系如下: * 如果 x.equals(y) 返回“true”,那么 x 和 y 的 hashCode() 必须相等。 * 如果 x.equals(y) 返回“false”,那么 x 和 y 的 hashCode() 有可能相等,也有可能不等。 例如,下面的代码将输出“相同 s1 的代码:123456 s2 的代码:123456”,因为 s1 和 s2 除了具有相同的值外,还具有相同的哈希码值: public class TestEquals { public static void main(String args[]) { Student s1 = new Student("张一", 6); Student s2 = new Student("张一", 6); if (s1.equals(s2)) { System.out.println("相同 s1 的代码:" + s1.hashCode() + " s2 的代码:" + s2.hashCode()); } else { System.out.println("不相同"); } } } class Student { private int age; private String name; public Student() {} public Student(String name, int age) { this.name = name; this.age = age; } @Override public boolean equals(Object obj) { if (obj instanceof Student) { Student s = (Student) obj; return this.name.equals(s.name) && this.age == s.age; } return false; } @Override public int hashCode() { int result = 17; result = 31 * result + name.hashCode(); result = 31 * result + age; return result; } } 在这个例子中,我们重写了 equals() 方法和 hashCode() 方法,用于比较两个 Student 对象的逻辑值是否相同。