ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
以下为 Object 中的通用方法 ```java public final native Class<?> getClass() public native int hashCode() public boolean equals(Object obj) protected native Object clone() throws CloneNotSupportedException public String toString() public final native void notify() public final native void notifyAll() public final native void wait(long timeout) throws InterruptedException public final void wait(long timeout, int nanos) throws InterruptedException public final void wait() throws InterruptedException protected void finalize() throws Throwable {} // JVM内存回收之finalize()方法 ``` ## equals() **1. equals() 与 == 的区别** - 对于基本类型,== 判断两个值是否相等,基本类型没有 equals() 方法。 - 对于引用类型,== 判断两个实例是否引用同一个对象,而 equals() 判断引用的对象是否等价。 ```java Integer x = new Integer(1); Integer y = new Integer(1); System.out.println(x.equals(y)); // true System.out.println(x == y); // false ``` **2. 等价关系** (一)自反性 ```java x.equals(x); // true ``` (二)对称性 ```java x.equals(y) == y.equals(x); // true ``` (三)传递性 ```java if (x.equals(y) && y.equals(z)) x.equals(z); // true; ``` (四)一致性 多次调用 equals() 方法结果不变 ```java x.equals(y) == x.equals(y); // true ``` (五)与 null 的比较 对任何不是 null 的对象 x 调用 x.equals(null) 结果都为 false ```java x.euqals(null); // false; ``` **3. 实现** - 检查是否为同一个对象的引用,如果是直接返回 true; - 检查是否是同一个类型,如果不是,直接返回 false; - 将 Object 实例进行转型; - 判断每个关键域是否相等。 ```java public class EqualExample { private int x; private int y; private int z; public EqualExample(int x, int y, int z) { this.x = x; this.y = y; this.z = z; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; EqualExample that = (EqualExample) o; if (x != that.x) return false; if (y != that.y) return false; return z == that.z; } } ``` ## hashCode()   hasCode() 返回散列值,而 equals() 是用来判断两个实例是否等价。**等价的两个实例散列值一定要相同,但是散列值相同的两个实例不一定等价。**   在覆盖 equals() 方法时应当总是覆盖 hashCode() 方法,保证等价的两个实例散列值也相等。   下面的代码中,新建了两个等价的实例,并将它们添加到 HashSet 中。我们希望将这两个实例当成一样的,只在集合中添加一个实例,但是因为 EqualExample 没有实现 hasCode() 方法,因此这两个实例的散列值是不同的,最终导致集合添加了两个等价的实例。 ```java EqualExample e1 = new EqualExample(1, 1, 1); EqualExample e2 = new EqualExample(1, 1, 1); System.out.println(e1.equals(e2)); // true HashSet<EqualExample> set = new HashSet<>(); set.add(e1); set.add(e2); System.out.println(set.size()); // 2 ```   理想的散列函数应当具有均匀性,即不相等的实例应当均匀分布到所有可能的散列值上。这就要求了散列函数要把所有域的值都考虑进来,可以将每个域都当成 R 进制的某一位,然后组成一个 R 进制的整数。R 一般取 31,因为它是一个奇素数,如果是偶数的话,当出现乘法溢出,信息就会丢失,因为与 2 相乘相当于向左移一位。   一个数与 31 相乘可以转换成移位和减法:`31\*x == (x<<5)-x`,编译器会自动进行这个优化。 ```java @Override public int hashCode() { int result = 17; result = 31 * result + x; result = 31 * result + y; result = 31 * result + z; return result; } ``` ## toString() 默认返回 ToStringExample@4554617c 这种形式,其中 @ 后面的数值为**散列码的无符号十六进制**表示。 ```java public class ToStringExample { private int number; public ToStringExample(int number) { this.number = number; } } ``` ```java ToStringExample example = new ToStringExample(123); System.out.println(example.toString()); ``` ```html ToStringExample@4554617c ``` ## clone() **1. cloneable** clone() 是 Object 的 protect 方法,它不是 public,一个类不显式去重写 clone(),其它类就不能直接去调用该类实例的 clone() 方法。 ```java public class CloneExample { private int a; private int b; } ``` ```java CloneExample e1 = new CloneExample(); // CloneExample e2 = e1.clone(); // 'clone()' has protected access in 'java.lang.Object' ``` 重写 clone() 得到以下实现: ```java public class CloneExample { private int a; private int b; @Override protected CloneExample clone() throws CloneNotSupportedException { return (CloneExample)super.clone(); } } ``` ```java CloneExample e1 = new CloneExample(); try { CloneExample e2 = e1.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } ``` ```html java.lang.CloneNotSupportedException: CloneTest ``` 以上抛出了 CloneNotSupportedException,这是因为 CloneTest 没有实现 Cloneable 接口。 ```java public class CloneExample implements Cloneable { private int a; private int b; @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } } ``` 应该注意的是,clone() 方法并不是 Cloneable 接口的方法,而是 Object 的一个 protected 方法。Cloneable 接口只是规定,如果一个类没有实现 Cloneable 接口又调用了 clone() 方法,就会抛出 CloneNotSupportedException。 参考资料: - [【必读】搞懂 Java equals 和 hashCode 方法 - 掘金](https://juejin.im/post/5ac4d8abf265da23a4050ae3)