方法摘要
1 | public final native Class<?> getClass() //获取对象的运行时对象的类 |
equals()
等价关系
- 自反性
1
x.equals(x) //true
- 对称性
1
x.equals(y) == y.equals(x) //true
- 传递性
1
2
3x.equals(y) //true
y.equals(z) //true
x.equals(z) //true - 一致性
多次调用 equals() 方法结果不变1
x.equals(y) == x.equals(y); // true
- 与 null 的比较
对任何不是 null 的对象 x 调用 x.equals(null) 结果都为 false1
x.equals(null); // false;
等价与相等
- 对于基本类型,==判断两个值是否相等,基本类型没有 equals() 方法
- 对于引用类型,==判断两个值的引用是否相等,而 equals() 方法判断引用的对象是否相等
1
2
3
4Integer x = new Integer(1);
Integer y = new Integer(1);
System.out.println(x.equals(y)); // true
System.out.println(x == y); // false
实现
- 检查是否为同一个对象的引用,如果是直接返回 true;
- 检查是否是同一个类型,如果不是,直接返回 false;
- 将 Object 对象进行转型;
- 判断每个关键域是否相等。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24public 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;
}
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()
hashCode 用于获取对象的 hash 值,表示在哈希表中的位置。
equals() 方法判断两个对象是否等价,等价的两个对象哈希值一定相等,而哈希值相等的两个对象不一定等价,因为计算哈希值具有随机性。
在覆盖 object 的 equals() 方法时应当总是覆盖 hashCode() 方法,保证等价的两个对象哈希值也是相等的
String 和 ArrayList 类都重写了 Object 的 equals() 方法,并重写了 hashCode() 方法
1 | public final class String |
重写 hashCode 方法时,需要用素数31作为乘子,因为31可以被 JVM 优化
- 左移 << : 左边的最高位丢弃,右边补全0(把 << 左边的数据*2的移动次幂)。
- 右移 >> : 把>>左边的数据/2的移动次幂。
- 无符号右移 >>> : 无论最高位是0还是1,左边补齐0。
所以 :31 * i = (i << 5) - i(左边 31 * 2=62,右边2 * 2^5-2=62)两边相等,JVM就可以高效的进行计算
toString
toString() 方法用于返回对象的字符串表示形式。默认返回格式:对象的 class 名称 + @ + hashCode 的十六进制字符串。
1 | public static void main(String[] args) { |
clone()
1. cloneable
clone() 是 Object 的 protected 方法,它不是 public,一个类不显式去重写 clone(),其它类就不能直接去调用该类实例的 clone() 方法。
1 | public class A { |
重写 clone() 方法,必须实现 Cloneable,因为 Cloneable 接口规定,如果一个类没有实现 Cloneable 接口又调用了 clone() 方法,就会抛出 java.lang.CloneNotSupportedException
1 | public class A implements Cloneable { |
2. 浅拷贝
拷贝对象和原始对象的引用类型引用同一个对象。
1 | public class A implements Cloneable { |
4. clone() 的替代方案
使用 clone() 方法来拷贝一个对象即复杂又有风险,它会抛出异常,并且还需要类型转换。Effective Java 书上讲到,最好不要去使用 clone(),可以使用拷贝构造函数或者拷贝工厂来拷贝一个对象。
1 | public class A { |