Java讀源碼之Object

前言

JDK版本: 1.8java

最近想看看jdk源碼提升下技術深度(比較閒),萬物皆對象,雖然Object大多native方法但仍是很重要的。app

源碼

package java.lang;

/**
 * Java中的始祖,萬物皆Object
 * @since   JDK1.0
 */
public class Object {

    private static native void registerNatives();
    static {
        // 保證在clinit()最早執行,從而調native方法
        registerNatives();
    }

    /**
     * 返回運行時的Class類文件,返回的是個泛型,運行時泛型會進行類型擦除,實際返回以自身爲邊界
     * 例如 new HelloWorld().getClass()
     * 返回 Class<? extends HelloWorld>
     */
    public final native Class<?> getClass();

    /**
     * 返回一個hash code整數,主要用於集合類使用,例如HashMap
     * 屢次調用返回值必須同樣,可是同一個應用執行了多份的時候,不保證多個執行中值相等
     * 若是兩個對象調equels方法返回ture,那麼hash code值必定相等(因此重寫equels方法必定要重寫hashCode方法)
     * 若是兩個對象調equels方法返回false,hash code值不必定不相等,可是咱們重寫hashCode方法時,應該儘可能作到不等,從而減小hash碰撞
     * 不一樣虛擬機的實現不太同樣,可是主要是根據對象的內存地址來計算的
     */
    public native int hashCode();

    /**
     * 對於非空的對象進行邏輯上是否相等的比較,默認是比較的內存地址
     * 再次強調哈哈,若是兩個對象調equels方法返回ture,那麼hash code值必定相等(因此重寫equels方法必定要重寫hashCode方法)
     * 四大特性(1)reflexive自反性(2)symmetric對稱性(3)transitive傳遞性(4)consistent一致性
     */
    public boolean equals(Object obj) {
        return (this == obj);
    }

    /**
     * 返回一個當前對象的副本,通常須要知足以下性質:
     *      x.clone() != x
     *      x.clone().getClass() == x.getClass()
     *      x.clone().equals(x)
     * 能夠根據須要實現淺拷貝和深拷貝,通常是淺拷貝
     * @throws  CloneNotSupportedException  Object沒有實現Cloneable接口,自己是不能使用clone方法的,其子類調用clone方法會拋出此異常.只有實現了Cloneable才能正常使用
     * @see java.lang.Cloneable
     */
    protected native Object clone() throws CloneNotSupportedException;

    /**
     * 返回一個對象的字符串表示
     * 建議全部類都重寫這個方法,由於不直觀
     * 字符串內容,類名加上hash code轉成16進制
     */
    public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }

    /**
     * 用於隨機喚醒一個在對象等待池中的線程
     * 被喚醒的線程不會馬上拿到對象的監視器鎖,而是和其餘在線程共同競爭,拿到鎖以後恢復到調用wait方法時的同步狀態
     * 同一時間只有一個線程能拿到監視器鎖
     *
     * @throws  IllegalMonitorStateException  若是當前執行notify方法的線程沒拿到對象的監視器鎖
     */
    public final native void notify();

    /**
     * 一次喚醒全部等待池中的線程,其餘和notify方法同樣
     */
    public final native void notifyAll();

    /**
     * 持有對象監視器的線程能夠執行awit方法把本身放入等待池中,而且放棄持有該對象的全部同步資源,不會放棄獲取的其餘對象的同步資源
     * 有四種狀況線程能夠逃出等待池:
     *      其餘線程調用notify方法
     *      其餘線程調用notifyAll方法
     *      其餘線程調用interrupts方法
     *      超時時間到了
     * 逃出等待池拿到鎖以後恢復到調用wait方法時的同步狀態
     * 特別強調,若是由於interrupts逃出了等待池,不會馬上拋出InterruptedException,須要等到線程拿到鎖
     * 因爲偶爾會發生僞喚醒(沒有調用notify或interrupts也沒超時),因此咱們在編碼時應該以下例:
     *      synchronized (obj) {
     *          while (<condition does not hold>)
     *              obj.wait(timeout);
     *              ... // Perform action appropriate to condition
     *      }
     * @param      timeout   在等待池中的最長等待時間,時間到了就出獄了,若是值爲0,則無期徒刑等待保釋
     * @throws  IllegalArgumentException     超時時間是負數
     * @throws  IllegalMonitorStateException  當前線程沒有拿到監視器鎖
     * @throws  InterruptedException 中斷位爲true
     */
    public final native void wait(long timeout) throws InterruptedException;

    /**
     * 提供納秒級別的等待控制,其餘同wait(long timeout)
     * @param      nanos     額外的納秒時間
     *                       0-999999.
     * @throws  IllegalArgumentException     timeout是負數,nanos是負數或者大於999999.
     */
    public final void wait(long timeout, int nanos) throws InterruptedException {
        if (timeout < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (nanos < 0 || nanos > 999999) {
            throw new IllegalArgumentException(
                                "nanosecond timeout value out of range");
        }

        if (nanos > 0) {
            timeout++;
        }

        wait(timeout);
    }

    /**
     * 和上面wait(long timeout)方法同樣,只是沒有超時時間
     */
    public final void wait() throws InterruptedException {
        wait(0);
    }

    /**
     * 當垃圾收集器判斷此對象沒有被任何引用,是垃圾對象了,由垃圾收集器執行此方法銷燬對象,因此什麼時候執行是不肯定的
     * JVM保證垃圾收集器調用此方法時候,該對象的鎖不被任何線程持有了
     * finalize方法只會被執行一次,因此咱們能夠重寫此方法特定一些清除工做,或者給對象一次復活機會,可是不建議重寫此方法
     * @throws Throwable the {@code Exception} raised by this method
     * @see java.lang.ref.WeakReference
     * @see java.lang.ref.PhantomReference
     */
    protected void finalize() throws Throwable { }
}

實踐

clone()

public class ObjectCloneTest {


    /**
     * 不實現 Cloneable 接口
     *
     * 輸出:
     * Exception in thread "main" java.lang.CloneNotSupportedException: study.ObjectCloneTest$Obj
     *  at java.lang.Object.clone(Native Method)
     *  at study.ObjectCloneTest$Obj.main(ObjectCloneTest.java:24)
     */
    private static class Obj {
        public static void main(String[] args) throws CloneNotSupportedException {
            Obj o1 = new Obj();
            Object o2 = o1.clone();
        }
    }

    /**
     * 實現 Cloneable 接口,從結果看出默認實現是淺拷貝
     *
     * 輸出:
     * 兩個對象地址相同麼
     * false
     * 兩個對象的屬性地址相同麼
     * true
     * 改變其中一個屬性會變麼?
     * [1, 2]
     * [1, 2]
     */
    private static class ObjShallowCopy implements Cloneable {

        private List<String> list = new ArrayList<>();

        @Override
        protected Object clone() throws CloneNotSupportedException {
            return super.clone();
        }

        public static void main(String[] args) throws CloneNotSupportedException {
            ObjShallowCopy o1 = new ObjShallowCopy();
            o1.list.add("1");
            ObjShallowCopy o2 = (ObjShallowCopy) o1.clone();
            System.out.println("兩個對象地址相同麼");
            System.out.println(o1 == o2);
            System.out.println("兩個對象的屬性地址相同麼");
            System.out.println(o1.list == o2.list);
            System.out.println("改變其中一個屬性會變麼?");
            o2.list.add("2");
            System.out.println(o1.list.toString());
            System.out.println(o2.list.toString());

        }

    }

    /**
     * 實現 Cloneable 接口,比較笨拙的作了一層深拷貝,只爲了演示,深拷貝也能夠經過序列號等方式實現
     *
     * 輸出:
     * 兩個對象地址相同麼
     * false
     * 兩個對象的屬性地址相同麼
     * false
     * 改變其中一個屬性會變麼?
     * [1]
     * [1, 2]
     */
    private static class ObjDeepCopy implements Cloneable {

        private List<String> list = new ArrayList<>();

        @Override
        protected Object clone() throws CloneNotSupportedException {
            ObjDeepCopy obj = (ObjDeepCopy) super.clone();
            List<String> list = new ArrayList<>(obj.list.size());
            list.addAll(obj.list);
            obj.list = list;
            return obj;
        }

        public static void main(String[] args) throws CloneNotSupportedException {
            ObjDeepCopy o1 = new ObjDeepCopy();
            o1.list.add("1");
            ObjDeepCopy o2 = (ObjDeepCopy) o1.clone();
            System.out.println("兩個對象地址相同麼");
            System.out.println(o1 == o2);
            System.out.println("兩個對象的屬性地址相同麼");
            System.out.println(o1.list == o2.list);
            System.out.println("改變其中一個屬性會變麼?");
            o2.list.add("2");
            System.out.println(o1.list.toString());
            System.out.println(o2.list.toString());

        }

    }
}

wait() 和 notify()

public class ObjectWaitNotifyTest {

    private volatile boolean flag = true;

    public static void main(String[] args) {
        ObjectWaitNotifyTest obj = new ObjectWaitNotifyTest();

        new Thread(() -> {
            synchronized (obj) {
                System.out.println("絕食!");
                while (obj.flag == true) {
                    try {
                        obj.wait();
                        System.out.println("真香!");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } 
                }
            }
        }).start();

        new Thread(() -> {
            synchronized (obj) {
                obj.flag = false;
                obj.notify();
                System.out.println("海底撈走起!");
            }
        }).start();

        /**
         * 輸出:
         * 絕食!
         * 海底撈走起!
         * 真香!
         */
    }
}
相關文章
相關標籤/搜索