equals()
equals()
方法只能用来判断两个对象是否相等,不能用于判断基本数据类型的变量。equals()
存在于 Object
类中且它是所有类的父类,所以所有类都有equals
方法。
1 | /** |
根据类是否重写了equals()
方法,有两种情况:
- 未重写:使用的默认是
Object
类的equals()
,等价于通过==
比较。 - 重写:如果两个对象的每个属性都相等,则返回
true
,否则返回false
。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21/**
* 调用 equals() 的两种情况
*/
class Person {
public String name;
public Person(String name) {
this.name = name;
}
}
Person person1 = new Person("bill");
Person person2 = new Person("frank");
String string1 = new String("ab");
String string2 = new String("ab");
// String 类重写了 equals 方法,返回 true
System.out.println(string1.equals(string2));
// Person 类没有重写 equals 方法,返回 false
System.out.println( person1.equals(person2));
== 和 equals()
区别:
equals()
是方法,而==
是操作符。- 对于基本类型,
==
是比较值的大小是否相同;而对于引用数据类型,==
比较的是对象的内存地址是否相同。因为 Java 只有值传递,所以对于
==
来说,不管是比较基本数据类型还是引用数据类型的变量,其本质比较的都是值,只是引用类型变量的值是内存地址。
1 | /** |
重写 equals()
思路:
如果是同一个对象的引用,直接返回
true
;如果比较对象为空或者不为同一个类型,直接返回
false
;将
Object
对象进行转型后,判断每个属性或关键域是否相等;
1 | /** |
hashCode()
- 因为
hashCode()
定义在Object
类中,所以任何类都包含hashCode()
。 - 因为计算哈希值具有随机性,所以两个值不同的对象可能计算出相同的哈希值。
1
2
3
4
5
6/**
* Object 的 hashCode()
* native 方法,用于返回对象的哈希码,主要使用在哈希表中,比如 JDK 中的 HashMap。
*/
public native int hashCode()Object
的hashCode()
是本地方法,是通过 C 或 C++ 实现的,通常用来将对象的内存地址转换为整数。
hashCode() 和 equals()
hashCode()
和equals()
的关系:
- 两个对象的哈希值相等,
equals()
不一定返回true
(哈希碰撞)。 - 两个对象的哈希值不相等,
equals()
一定返回false
。 equals()
返回true
时,两个对象的哈希值一定相等。重写 equals 方法时也需要重写 hashCode 方法,这是因为:必须保证 equals 方法判断两个对象相等时,hash 值也相等。
重写 hashCode()
重写hashCode
,可以使用Objects.hash()
方法实现,通过类的所有属性生成最终的哈希值。
1 | /** |
Objects.hash()
中调用了Arrays.hashCode()
,通过循环将每一个属性的哈希值都计算在内:
1 | // Objects.hash() |
toString()
返回类的名字实例的哈希值的 16 进制字符串,所有的子类最好重写 toString 方法。
1 | /** |
clone()
1 | /** |
重写 clone()
clone()
在Object
中的权限修饰符为protected
,所以如果一个类不显式重写clone()
,那新建类时就不能调用该类实例的clone()
方法。
1 | public class CloneExample { |
类在重写clone()
时还需要实现Cloneable
接口,不然会抛出CloneNotSupportedException
异常。
1 | public class CloneExample { |