一、Object对象简介
Object
类是java.lang
包下的核心类,是所有类的父类
所有的Java对象都隐式地继承了Object
对象(不用写extends
继承)
所有的对象都拥有Object默认的方法
那么先来看一看Object都有些什么方法:
registerNatives()
底层实现
clone()
克隆(复制)
equals()
对象值比较
finalize()
垃圾回收前调用的方法
getClass()
返回字节码文件对象class
hashCode()
对象的hash值
notify()
唤醒线程
notifyAll()
唤醒全部线程
toString()
获取对象的信息
wait()
线程等待
二、equals和hashCode方法
equals()
比较对象的地址是否相等,如果子类重写,则比较对象的内容是否相等
public native int hashCode();
public boolean equals(Object obj) {
return (this == obj);
}
hashCode()
由native
方法底层实现equals()
直接==
判断是否相等
equals()
方法默认比较对象的地址,使用==
等值运算符
equals()方法的默认原则:
- 自反性:
x.equals(x)
必须返回true
- 一致性:只要对象没有被修改,那么多次调用还是返回对应的结果
- 传递性:
x.equals(y)
和y.equals(z)
都返回true
,那么x.equals(z)
也返回true
- 对称性:
x.equals(y)
和y.equals(x)
结果应该是相等的 - 任何情况下
x.equals(null)
,都会返回false
hashCode()方法对底层是散列表的对象有提升性能的功能
1、equals和hashCode方法重写
equals()
方法默认比较对象的地址,使用的是==
运算符
重写equals()
方法,就必须重写hashCode()
方法,以保证相同的对象返回相同的hash值,不同的对象返回不同的hash值
为什么要重写equals方法?
equals是Object中的方法,其源码如下:
可以看出,equals默认使用==
来比较,而==
对于基本数据类型,比较的是值,对于引用数据类型,比较的是内存地址。
根据hashCode的规范,我们重写了equals()
就必须重写hashCode()
为什么要重写hashCode()?
hashCode是用于散列数据的快速存取,如利用HashSet/HashMap/Hashtable 类来存储数据时,都会根据存储对象的 hashCode
值来进行判断是否相同。
由于Object的hashCode返回的是对象的hash值,所以即使equals返回TRUE,集合也可能判定两个对象不等,所以必须重写hashCode方法,以保证当equals返回TRUE时,hashCode也返回Ture,这样才能使得集合中存放的对象唯一
两个对象用equals方法比较结果为true,他们的hashcode值相同么?
不一定相同。正常情况下,因为equals()方法比较的就是对象在内存中的值,如果值相同,那么Hashcode值也应该相同。但是如果不重写hashcode方法,就会出现不相等的情况。
2、String实现的equals和hashCode方法
String已经实现了equals和hashCode方法
所以,我们可以直接使用String.equals()
来判断两个字符串
是否相等
三、toString方法
在实际开发中,通常希望对象的toString()
方法返回的不仅仅是基本信息,而是一些特有的信息,这时重写Object的toString()
方法便可以实现。
toString()
以文本的方式来表示一个对象,可以根据实际需要重写toString()
来编写打印结果
@Override
public String toString() {
return "Student{" +
"姓名:'" + name + '\'' +
", 成绩:'" + grades + '\'' +
'}';
}
四、clone方法
- clone方法用于对象的克隆,一般克隆出的对象是
独立
的(与原有的对象分开) - 深层克隆指的是该对象的成员变量(如果是可变引用)都应该克隆一份,浅克隆指的是成员变量没有被克隆一份
浅克隆:基本数据类型属性完全重新创建,引用类型属性依然共用的克隆
深克隆:所有类型属性都完全重新创建
如何使用克隆?
无论是深克隆还是浅克隆:
- 克隆的对象要
实现Cloneable接口
-
重写克隆方法
,最好修饰成public
clone()
是Object
的protected
方法,他不是public
方法,一个类不显示地重写clone()
,其它类就不能直接去调用该类实例的 clone()
方法
应该注意的是, clone()
⽅法并不是 Cloneable
接⼝的⽅法,而是 Object
的一个 protected
⽅法。Cloneable
接口只是规定,如果一个类没有实现 Cloneable
接口又调用了 clone()
⽅法,就会抛出CloneNotSupportedException
浅克隆:仅仅克隆了Person对象,而name没有克隆!
public class Person implements Cloneable {
// 可变的成员变量
private String name;
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
深克隆:不仅克隆了Person对象,也克隆了name成员变量
public class Person implements Cloneable {
// 可变的成员变量
public String name;
@Override
public Object clone() throws CloneNotSupportedException {
// 克隆Person对象
Person person = (Person) super.clone();
// 将可变的成员变量也克隆
person.name = (String) name.clone();
// 返回克隆的对象
return person;
}
}