中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java基礎知識之Object類

發布時間:2020-07-17 01:13:04 來源:網絡 閱讀:184 作者:專注地一哥 欄目:編程語言

package 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
br/>@Override
return super.clone();}
@Override
br/>}
@Override
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();

  1. 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值也是相同的
  2. 對于兩個對象來說,如果使用equals方法比較為false,那么這兩個對象的hash值不一定要求不同,可以相同也可以不同,然而如果不同,則可以提高性能4. 對于Object類來說,不同的Object對象的hashcode是不同的(Object的hashcode 表示對象的存儲地址,但是如果重寫了hashcode 就不一定表示存儲地址了)
  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
        br/>@Override
        return "User{" +
        "name='" + name + '\'' +
        ", age=" + age +'}';
        }
        @Override
        br/>'}';
        }
        @Override
        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.ObjectTest
        finalize
        Process finished with exit code 0
        可以看到結果:兩次gc finalize 只執行了一次
  6. wait()? notify() notifyAll()
    這三個方法是有關線程阻塞與線程喚醒
  7. wait(),notify()與notifyAll()方法是本地方法,并且是final類型,無法重寫
  8. 調用某個對象的wait()方法能讓當前線程阻塞,并且當前線程必須擁有此對象的monitor(即鎖)
  9. 調用某個對象的notify()方法能喚醒一個正在等待這個對象的monitor的線程,如果有多個線程在等待這個monitor,喚醒其中一個線程;
  10. 調用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
    br/>@Override
    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
    br/>@Override
    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
    1、Object類的七大native方法:registerNatives()、getClass()、hashCode()、clone()、notify()、notifyAll()、wait(long)native關鍵字修飾的方法稱為本地方法,這些方法并不是用java實現的,考慮到實現的性能問題,大多是由C/C++編寫的程序,編譯成dll文件,再由java去加載這些dll文件,就可以通過java來調用dll中的函數了1)registerNatives()方法:主要是將用C/C++語言寫的一些方法,如hashCode、wait、notify等方法加載到jvm中,感興趣的可以去OpenJDK中查看相關C的代碼如下static JNINativeMethod methods[] = {  {“hashCode”, “()I”, (void )&JVM_IHashCode},  {“wait”, “(J)V”, (void )&JVM_MonitorWait},  {“notify”, “()V”, (void )&JVM_MonitorNotify},  {“notifyAll”, “()V”, (void )&JVM_MonitorNotifyAll},  {“clone”, “()Ljava/lang/Object;”, (void )&JVM_Clone},};JNIEXPORT void JNICALLJava_java_lang_Object_registerNatives(JNIEnv env, jclass cls)
    {
      (*env)->RegisterNatives(env, cls,methods, sizeof(methods)/sizeof(methods[0]));
    }
    2)getClass()方法:我們可以看到這個方法是由final修飾的,因此不能被重寫的,對final關鍵字不太了解的,可以看一下我的另一篇文章:Java源碼解析之 final關鍵字的使用詳解//class 是一個類的屬性,能獲取該類編譯時的類對象
    System.out.println(Bird.class);//class com.somta.test.commonuseobj.objectobj.Bird//getClass() 是一個類的方法,它是獲取該類運行時的類對象
    System.out.println(bird.getClass());//class com.somta.test.commonuseobj.objectobj.Bird
    3)hashCode()方法:返回一個整數的HashCode值,該值依賴于內部表示堆的對象的指針,一般情況下,該方法都會被重寫。關于hashCode與equals的關系,我們只需要記住下面四句話(前提:需要重寫equals和hashCode方法,String、Integer、Boolean、Double等都重寫了這兩個方法,不重寫HashCode方法,任何對象的hashCodeZFX返傭www.fx61.com/brokerlist/zfx.html都是不相等的,并且equals方法也會使用Object中的equals方法,此時equals和==是等價的,equals比較的是棧中的引用,而非對象的值)1、如果兩個對象相等,則它們的hashCode值一定相等
    2、如果兩個對象不相等,則它們的hashCode值不一定都不相等
    3、如果兩個對象的hashCode值相等,兩個對象不一定相等
    4、如果兩個對象的hashCode值不相等,兩個對象一定不相等4)clone()方法: 將一個對象克隆出一個新對象,要實現clone的對象一般需要先實現Cloneable接口才能達到克隆的目的,克隆其實也分“淺克隆”,“深克隆” ,Object類的克隆屬于“淺克隆”,關于克隆的知識,后續在寫文章說明,此處就不展開了5)notify()、notifyAll()、wait(long)方法: 這些方法后續在多線程中在具體講解2、Object類的常用方法:equals()、toString()
    1)、equals()方法我們可能在以前的面試中被問到過關于 == 和 equals的區別,可能大多人的回答是:“==運算符通常是用來比較基本類型的值是否相等或者比較對象的引用是否相等;equals比較的是兩個對象是否相等”,這種說法其實并不太正確,不妨我們先看Object中關于equals()方法的源碼public boolean equals(Object obj) {
    return (this == obj);
    }
    Object類是所有類的子類,如果一個類沒有重寫equals()方法,那它就會使用父類的的equals()方法,通過上面的代碼可以看出其實在Object類中,==運算符和equals()方法是等價的,其實上面的說法只適用于那些重寫了Object類equals方法的類而言是正確的,比如String等。注意:重寫equals()方法的時候,必須要重寫hashCode方法,以維護hashCode的約束,確保equals()方法聲明相等的對象具有相同的hashCode值2)、toString()方法public String toString() {
    return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }
    getClass().getName()返回了該類的全類名,Integer.toHexString(hashCode())返回了以16進制無符號整數的形式返回了此hashCode的字符串,這個是根類Object的實現,子類中一般都會重寫該方法
向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

石楼县| 三门峡市| 衡南县| 丘北县| 湟中县| 嘉义市| 连山| 镇江市| 叶城县| 焦作市| 隆林| 陵川县| 万安县| 横山县| 固安县| 巩义市| 上高县| 峨眉山市| 久治县| 桑日县| 南宁市| 礼泉县| 栾川县| 西平县| 乐至县| 九江县| 吉水县| 藁城市| 阿克苏市| 祁东县| 乌兰浩特市| 西贡区| 禹州市| 桑日县| 海林市| 保靖县| 个旧市| 嫩江县| 永城市| 太康县| 绵阳市|