寫在開頭
在上一篇博文中我們提到了Java面向對象的四大特性,其中談及“抽象”特性時做了一個引子,引出今天的主人公Object,作為所有類的頂級父類,Object被視為是James.Gosling的哲學思考,它高度概括了事務的自然與社會行為。
源碼分析
跟進Object類的源碼中我們可以看到,類的注釋中對它做了一個總結性的注釋。
在Object的內部主要提供了這樣的11種方法,大家可以在源碼中一個個的跟進去看,每個方法上均有詳細的英文注釋,養(yǎng)成良好的看英文注釋習慣,是一個合格程序員的必備基礎技能哈。
/**
* 方法一
*/
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 { }
getClass()
getClass()是Java的一個native 方法,用于返回當前運行時對象的 Class 對象,使用了 final 關鍵字修飾,故不允許子類重寫。在源碼中我們可以到,該方法的返回是Class類。
Class 類存放類的結構信息,能夠通過 Class 對象的方法取出相應信息:類的名字、屬性、方法、構造方法、父類、接口和注解等信息。
hashCode()
同樣是native 方法,用于返回對象的哈希碼,主要使用在哈希表中,比如 JDK 中的HashMap。
equals()
默認比較對象的地址值是否相等,子類可以重寫比較規(guī)則,如String 類對該方法進行了重寫以用于比較字符串的值是否相等。
clone()
native 方法,用于創(chuàng)建并返回當前對象的一份拷貝。
toString()
返回類的名字實例的哈希碼的 16 進制的字符串。建議 Object 所有的子類都重寫這個方法。
notify()
native 方法,并且不能重寫。喚醒一個在此對象監(jiān)視器上等待的線程(監(jiān)視器相當于就是鎖的概念)。如果有多個線程在等待只會任意喚醒一個。
notifyAll()
native 方法,并且不能重寫。跟 notify 一樣,唯一的區(qū)別就是會喚醒在此對象監(jiān)視器上等待的所有線程,而不是一個線程。
wait(long timeout)
native方法,并且不能重寫。暫停線程的執(zhí)行。注意:sleep 方法沒有釋放鎖,而 wait 方法釋放了鎖 ,timeout 是等待時間。
wait(long timeout, int nanos)
多了 nanos 參數(shù),這個參數(shù)表示額外時間(以納秒為單位,范圍是 0-999999)。 所以超時的時間還需要加上 nanos 納秒。
wait()
讓持有對象鎖的線程進入等待,不可設置超時時間,沒有被喚醒的情況下,會一直等待。
finalize()
實例被垃圾回收器回收的時候觸發(fā)的操作
高頻面試考點總結
雖然在日常的代碼開發(fā)中,我們很少會直接使用Object類,但考慮到它的獨特地位,與此相關的面試考點還是不少的,我們今天總結一下。
1.淺拷貝、深拷貝、引用拷貝的區(qū)別?
淺拷貝:基本類型的屬性會直接復制一份,而引用類型的屬性復制:復制棧中的變量和變量指向堆內存中的對象的指針,不復制堆內存中的對象,也就是說拷貝對象和原對象共用同一個內部對象。
深拷貝:深拷貝會完全復制整個對象,包括這個對象所包含的內部對象。
引用拷貝:簡單來說,引用拷貝就是兩個不同的引用指向同一個對象。
2.Java中如何實現(xiàn)淺拷貝與深拷貝
其實實現(xiàn)淺拷貝很簡單,實現(xiàn) Cloneable 接口,重寫 clone() 方法,在clone()方法中調用父類Object的clone()方法。
public class TestClone {
public static void main(String[] args) throws CloneNotSupportedException {
Person p1 = new Person(1, "ConstXiong");//創(chuàng)建對象 Person p1
Person p2 = (Person)p1.clone();//克隆對象 p1
p2.setName("其不答");//修改 p2的name屬性,p1的name未變
System.out.println(p1);
System.out.println(p2);
}
}
/**
* person類
*/
class Person implements Cloneable {
private int pid;
private String name;
public Person(int pid, String name) {
this.pid = pid;
this.name = name;
System.out.println("Person constructor call");
}
public int getPid() {
return pid;
}
public void setPid(int pid) {
this.pid = pid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
public String toString() {
return "Person [pid:"+pid+", name:"+name+"]";
}
}
那么如何實現(xiàn)深拷貝呢,這里給出兩種方法
方法一:將對象的屬性的Class 也實現(xiàn) Cloneable 接口,在克隆對象時也手動克隆屬性。
方法二:結合序列化(JDK java.io.Serializable 接口、JSON格式、XML格式等),完成深拷貝。
3.==和equals的區(qū)別是什么?
**區(qū)別**
== 是關系運算符,equals() 是方法,結果都返回布爾值
Object 的 == 和 equals() 比較的都是地址,作用相同
**== 作用:**
基本類型,比較值是否相等
引用類型,比較內存地址值是否相等
不能比較沒有父子關系的兩個對象
**equals()方法的作用:**
JDK 中的類一般已經(jīng)重寫了 equals(),比較的是內容
自定義類如果沒有重寫 equals(),將調用父類(默認 Object 類)的 equals() 方法,Object 的 equals() 比較使用了 this == obj
可以按照需求邏輯,重寫對象的 equals() 方法(重寫 equals 方法,一般須重寫 hashCode 方法)
4.為什么說重寫equals方法也要重寫hashCode方法呢?
equals()方法是用來判斷兩個對象是否相等的重要方法,Object中默認比較地址,但這在實際使用上意義不大,比如兩個字符串,我們比較的初衷肯定是他們的字符串內容是否相等,而不是內存地址,典型的就是String內部的重寫equals。
hashCode()方法是一個C或C++實現(xiàn)的本地方法,用以獲取對象的哈希碼值(散列碼),通過碼值可以確定該對象在哈希表中的索引位置,是通過線程局部狀態(tài)來實現(xiàn)的隨機數(shù)值。子類可通過重寫該方法去重新設計hash值。
使用hashCode方法可以一定程度上判斷兩個對象是否相等,因為,若兩個對象相等,那么他們所在的索引位置肯定就一樣,這時hashCode獲取的哈希碼自然也就一樣,但這個條件反過來就不一定成立了,哈希碼相等的兩個對象不一定相等,因為存在哈希碰撞 。文章來源:http://www.zghlxwxcb.cn/news/detail-788587.html
看完這兩個方法的特點,我們大概可以明白了,確保兩個對象是否真正相等,需要這個兩個方法的協(xié)作,equals是邏輯上的相等,hashCode是物理上的相等,若我們在重寫equals()方法時,不去重寫配套的hashCode方法,就會導致兩個對象在邏輯上相等,但物理上不等,這會帶來很多問題,譬如集合類HashMap的底層實現(xiàn)是數(shù)據(jù)+鏈表/紅黑樹的方式,通過計算hash尋找位置,通過equals判斷元素相等,這時候若僅重寫equals的話,hash不重寫,就會出現(xiàn)邏輯上我們認為相等的兩個數(shù),存在了不同的位置上,造成混亂的場面。文章來源地址http://www.zghlxwxcb.cn/news/detail-788587.html
到了這里,關于作為所有類的頂層父類,沒想到Object的魔力如此之大!的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!