你真的瞭解Object源碼嗎

歡迎點贊閱讀,一同窗習交流,有疑問請留言 。
GitHub上也有開源 JavaHouse 歡迎starjava

引入

Object 應該是比較簡單的源碼了。如今咱們來分析一下他。Object 是類層次結構的根。Java體系裏面的每一個類默認都有一個超類就是 Object。總之,全部對象,包含數組,都默認實現該類的方法。c++

native 關鍵字

由於 Object 類裏面有不少地方都用到 native 關鍵字。咱們先了解一下這傢伙。native 關鍵字是 JNI(Java Native Interface)的重要體現。什麼是 JNI ,JNI 是Java調用其餘語言(c,c++) 的一種機制。native 關鍵字修飾的是方法,起聲明做用,告訴 JVM 老哥本身去調用這個方法。 這個方法的實如今別的語言那裏已經實現,咱們是看不到源碼的。git

初始化

private static native void registerNatives();
static {
    registerNatives();
}

源碼裏面一個靜態塊,一個靜態方法和一個沒有顯示的默認構造方法,沒有成員變量。能夠看出來 registerNatives() 方法只會被調用一次。github

getClass() 方法

public final native Class<?> getClass();

getClass()方法被native修飾,告訴 JVM 本身去調用。同時被 final 修飾,因此不能被子類重寫。主要做用是返回正在運行的類別(Class)。數組

hashCode() 方法

public native int hashCode();

getClass()方法被native修飾,告訴 JVM 本身去調用,能夠被重寫。同時被 final 修飾,因此不能被子類重寫。該方法主要是返回對象的hashcode,主要是爲了一些哈希表的數據結構服務的,好比 HashMap 。微信

在 Java 中hancode 與 對象是否相等密切相關。 若是兩個對象相等,則 hashcode 必定相等,可是 hashcode 相等,兩個對象不必定相等。若是 hashcode 不相等,那麼這兩個對象必定不相等。數據結構

equals(Object obj)

public boolean equals(Object obj) {
    return (this == obj);
}

該方法能夠被重寫,主要用來判斷兩個對象是否相等。多線程

該方法有一些約定。ide

  1. 對象任意一個非空對象x, x.equals(x) 返回 true。
  2. 對象任意兩個非空對象 x,y,若是 x.equals(y) 返回true,那麼 y.equals(x) 也會返回true, 具備對稱性。
  3. 對象任意三個非空對象 x,y,z,若是 x.equals(y) 返回true, y.equals(z) 返回true, 那麼x.equals(z) 返回true, 具備傳遞性。
  4. 對象任意兩個非空對象 x,y,在什麼發生變化的狀況寫,x.equals(y) 返回老是 true 或者 flase,具備一直性。
  5. 對象任意一個非空對象x, x.equals(null) 返回 false。

Object#equals(Object obj)方法,比較的是內存地址,一般實際應用中咱們想比較的是兩個對象裏面的屬性內容是否相等,因此會重寫該方法。這裏要注意重寫 equals(Object obj) 的時候,也要重寫 hashCode() 方法。 由於 Java 規定:若是兩個對象相等,那麼他們的 hashcode 也要相等。舉個 Integer 的例子:學習

@Override
public boolean equals(Object obj) {
    if (obj instanceof Integer) {
        return value == ((Integer)obj).intValue();
    }
    return false;
}

@Override
public int hashCode() {
    return Integer.hashCode(value);
}

public static int hashCode(int value) {
    return value;
}

clone()

protected native Object clone() throws CloneNotSupportedException;

該方法被native修飾,告訴 JVM 本身去調用。當咱們在自定義類中使用該方法的時候,須要繼承一個 Cloneable 接口,不然會拋出沒法克隆的異常。該方法是一個淺複製,不是深複製。

淺拷貝:對基本數據類型進行值傳遞,對引用數據類型進行引用傳遞般的拷貝,此爲淺拷貝。
深拷貝:對基本數據類型進行值傳遞,對引用數據類型,建立一個新的對象,並複製其內容,此爲深拷貝。

  • 使用代碼
@Data
public class Person extends Man implements Cloneable {
    private String name;
    private Person person;

    public static void main(String[] args) throws CloneNotSupportedException {
        Person person = new Person();
        person.setName("chen");
        Person clone = (Person)person.clone();
        System.out.println(clone.toString());
        System.out.println("person.equals(clone):"+person.equals(clone));
        System.out.println("person == clone:"+(person == clone));
        System.out.println("person.person == clone.person:"+(person.person == clone.person));
    }
  • 結果
Person(name=chen, person=null)
person.equals(clone):true
person == clone:false
person.person == clone.person:true

notify()、notifyAll() 和 wait()

public final native void notify();
public final native void notifyAll();
public final void wait() throws InterruptedException {
        wait(0);
    }

notify() 隨機喚醒一個等待線程,notifyAll() 喚醒所有的等待線程。wait() 方法讓當前線程進入等待狀態。

流程圖

不管當前線程調用哪一個方法,都有一個前提:當前線程擁有對象的監視器。實現方法也很簡單,配合 synchronized 關鍵字使用。

  • 實現方法
synchronized (obj) {
    while (true)
        obj.wait();
        // obj.notify();          
}

舉一個實際的例子

  • 多線程打印奇偶數
public static void main(String[] args) {
        Thread thread = new Thread(() -> {
        for ( int i = 0; i < 100; i += 2) {
            synchronized (a) {
                System.out.println(Thread.currentThread().getName()+":"+i);
                try {
                    a.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        });
        Thread thread1 = new Thread(() -> {
            for (int i = 1; i < 100; i += 2) {
                synchronized (a) {
                    System.out.println(Thread.currentThread().getName()+":"+i);
                    a.notify();
                }
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        thread.start();thread1.start();
    }

finalize()

protected void finalize() throws Throwable { }

當垃圾回收器肯定再也不有對該對象的引用時,由垃圾回收器在對象上調用該方法。該方法只會被調用一次。

參考

若是個人文章幫助到您,能夠關注個人微信公衆號,第一時間分享文章給您 公衆號.jpg

相關文章
相關標籤/搜索