Java源碼之Object類__java

來源:互聯網
上載者:User
  // IntelliJ API Decompiler stub source generated from a class file  // Implementation of methods is not availablepackage java.lang;public class Object {    public Object() { /* compiled code */ }    private static native void registerNatives();    public final native java.lang.Class<?> getClass();    public native int hashCode();    public boolean equals(java.lang.Object o) { /* compiled code */ }    protected native java.lang.Object clone() throws java.lang.CloneNotSupportedException;    public java.lang.String toString() { /* compiled code */ }    public final native void notify();    public final native void notifyAll();    public final native void wait(long l) throws java.lang.InterruptedException;    public final void wait(long l, int i) throws java.lang.InterruptedException { /* compiled code */ }    public final void wait() throws java.lang.InterruptedException { /* compiled code */ }    protected void finalize() throws java.lang.Throwable { /* compiled code */ }}
Object是java所有類的終極類,我們常見的自訂class 但是並沒有繼承Object(Java編譯器自動引入,如果手動繼承Object,也是沒有問題的,java單繼承 有一定的局限)
    public static class User {        @Override        protected Object clone() throws CloneNotSupportedException {            return super.clone();        }        @Override        public int hashCode() {            return super.hashCode();        }    }


Object類  約12個方法,下面一一解釋這些方法的作用

1. getClass()

  public final Class<?> getClass() {      return shadow$_klass_;    }
返回此Object的運行時類
實際結果的類型是Class<? extends |X|>其中|X|是靜態類型上其表達的擦除getClass被調用。 例如,在此程式碼片段中不需要轉換:
Number n = 0; 
Class<? extends Number> c = n.getClass();

2. hashCode()

   /* @return  a hash code value for this object.     * @see     java.lang.Object#equals(java.lang.Object)     * @see     java.lang.System#identityHashCode     */    public int hashCode() {        return identityHashCode(this);    }
返回對象的hash值,支援這種方法是為了散列表,如hashmap
hashcode 的特點是:
1.只要在執行Java應用程式時多次在同一個對象上調用該方法,hashcode()始終返回相同的整數(前提是該對象的資訊沒有發生改變)
2.相對於兩個對象來說,如果使用了equals方法比較返回true,那麼這兩個對象的hashcode值也是相同的

3. 對於兩個對象來說,如果使用equals方法比較為false,那麼這兩個對象的hash值不一定要求不同,可以相同也可以不同,然而如果不同,則可以提高效能
4. 對於Object類來說,不同的Object對象的hashcode是不同的(Object的hashcode 表示對象的儲存地址,但是如果重寫了hash code 就不一定表示儲存地址了)

3. Clone()

    protected Object clone() throws CloneNotSupportedException {        if (!(this instanceof Cloneable)) {            throw new CloneNotSupportedException("Class " + getClass().getName() +                                                 " doesn't implement Cloneable");        }        return internalClone();    }
複製方法:建立並返回此對象的副本 ; 對於任何對象x x.clone()!=x
而且x.clone().getClass()==x.getClass() 成立 雖然對象的基類都支援clone 但是object本身並未實現cloneable,所以自訂的類需要實現cloneable介面,否則將拋出異常 4. toString()

返回對象的字串表示形式,一般說來,這個方法返回一個固定的模版

public String toString() {        return getClass().getName() + "@" + Integer.toHexString(hashCode());    }
這個在實際開發中,並不好體現,所以各大編譯器都支援 重建toString(),如:
 public static class User {       private String name;       private int age;        @Override        public String toString() {            return "User{" +                    "name='" + name + '\'' +                    ", age=" + age +                    '}';        }    }
5. finalize()
 /* @throws Throwable the {@code Exception} raised by this method     * @see java.lang.ref.WeakReference     * @see java.lang.ref.PhantomReference     * @jls 12.6 Finalization of Class Instances     */    protected void finalize() throws Throwable { }
finalize()方法可以被子類對象所覆蓋,然後作為一個終結者,當GC被調用的時候完成最後的清理工作(例如釋放系統資源之類)。這就是終止。預設的finalize()方法什麼也不做,當被調用時直接返回。
對於任何一個對象,它的finalize()方法都不會被JVM執行兩次。如果你想讓一個對象能夠被再次調用的話(例如,分配它的引用給一個靜態變數),注意當這個對象已經被GC回收的時候,finalize()方法不會被調用第二次。

測試:
package asange.javastudy.java.lang;/** * @author youxuan  E-mail:xuanyouwu@163.com * @version 2.3.1 * @Description * @date createTime:2018/1/20 */public class ObjectTest {    public static class User {        private String name;        private int age;        @Override        public String toString() {            return "User{" +                    "name='" + name + '\'' +                    ", age=" + age +                    '}';        }        @Override        protected void finalize() throws Throwable {            System.out.println("finalize");            super.finalize();        }    }    public static void main(String[] args) throws Exception {        User o = new User();        o = null;        System.gc();        System.gc();    }}


運行結果:

asange.javastudy.java.lang.ObjectTestfinalizeProcess finished with exit code 0
可以看到結果:兩次gc finalize 只執行了一次


6. wait()  notify() notifyAll() 這三個方法是有關線程阻塞與線程喚醒
1. wait(),notify()與notifyAll()方法是本地方法,並且是final類型,無法重寫
2. 調用某個對象的wait()方法能讓當前線程阻塞,並且當前線程必須擁有此對象的monitor(即鎖)
3. 調用某個對象的notify()方法能喚醒一個正在等待這個對象的monitor的線程,如果有多個線程在等待這個monitor,喚醒其中一個線程;
4. 調用notifyAll()方法能喚醒所有正在等待這個對象的monitor

為何這三個不是Thread類聲明中的方法,而是Object類中聲明的方法(當然由於Thread類繼承了Object類,所以Thread也可以調用者三個方法)。其實這個問題很簡單,由於每個對象都擁有monitor(即鎖),所以讓當前線程等待某個對象的鎖,當然應該通過這個對象來操作了。而不是用當前線程來操作,因為當前線程可能會等待多個線程的鎖,如果通過線程來操作,就非常複雜了。
  上面已經提到,如果調用某個對象的wait()方法,當前線程必須擁有這個對象的monitor(即鎖),因此調用wait()方法必須在同步塊或者同步方法中進行(synchronized塊或者synchronized方法)。
  調用某個對象的wait()方法,相當於讓當前線程交出此對象的monitor,然後進入等待狀態,等待後續再次獲得此對象的鎖(Thread類中的sleep方法使當前線程暫停執行一段時間,從而讓其他線程有機會繼續執行,但它並不釋放對象鎖);
  notify()方法能夠喚醒一個正在等待該對象的monitor的線程,當有多個線程都在等待該對象的monitor的話,則只能喚醒其中一個線程,具體喚醒哪個線程則不得而知。
  同樣地,調用某個對象的notify()方法,當前線程也必須擁有這個對象的monitor,因此調用notify()方法必須在同步塊或者同步方法中進行(synchronized塊或者synchronized方法)。

  nofityAll()方法能夠喚醒所有正在等待該對象的monitor的線程,這一點與notify()方法是不同的。


  這裡要注意一點:notify()和notifyAll()方法只是喚醒等待該對象的monitor的線程,並不決定哪個線程能夠擷取到monitor。


  舉個簡單的例子:假如有三個線程Thread1、Thread2和Thread3都在等待對象objectA的monitor,此時Thread4擁有對象objectA的monitor,當在Thread4中調用objectA.notify()方法之後,Thread1、Thread2和Thread3隻有一個能被喚醒。注意,被喚醒不等於立刻就擷取了objectA的monitor。假若在Thread4中調用objectA.notifyAll()方法,則Thread1、Thread2和Thread3三個線程都會被喚醒,至於哪個線程接下來能夠擷取到objectA的monitor就具體依賴於作業系統的調度了。


  上面尤其要注意一點,一個線程被喚醒不代表立即擷取了對象的monitor,只有等調用完notify()或者notifyAll()並退出synchronized塊,釋放對象鎖後,其餘線程才可獲得鎖執行。

public class ObjectTest {     public static Object obj = new Object();    public static void main(String[] args) throws Exception {        Object o2 = new Object();        Thread1 thread1 = new Thread1();        Thread2 thread2 = new Thread2();        thread1.start();        thread2.start();    }    static class Thread1 extends Thread {        @Override        public void run() {            super.run();            System.out.println("線程" + Thread.currentThread().getName() + "開始");            synchronized (obj) {                try {                    System.out.println("線程" + Thread.currentThread().getName() + "調用了object.wait()");                    obj.wait();                } catch (InterruptedException e) {                    e.printStackTrace();                }                System.out.println("線程" + Thread.currentThread().getName() + "擷取到了鎖");            }        }    }    static class Thread2 extends Thread {        @Override        public void run() {            super.run();            System.out.println("線程" + Thread.currentThread().getName() + "開始");            synchronized (obj) {                obj.notify();                System.out.println("線程" + Thread.currentThread().getName() + "調用了object.notify()");            }            System.out.println("線程" + Thread.currentThread().getName() + "釋放了鎖");        }    }}

運行結果:

線程Thread-0開始線程Thread-1開始線程Thread-0調用了object.wait()線程Thread-1調用了object.notify()線程Thread-1釋放了鎖線程Thread-0擷取到了鎖Process finished with exit code 0


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.