1. 程式人生 > >你真的瞭解Object原始碼嗎

你真的瞭解Object原始碼嗎

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

引入

Object 應該是比較簡單的原始碼了。現在我們來分析一下他。Object 是類層次結構的根。Java體系裡面的每個類預設都有一個超類就是 Object。總之,所有物件,包含陣列,都預設實現該類的方法。

native 關鍵字

因為 Object 類裡面有很多地方都用到 native 關鍵字。我們先了解一下這傢伙。native 關鍵字是 JNI(Java Native Interface)的重要體現。什麼是 JNI ,JNI 是Java呼叫其他語言(c,c++) 的一種機制。native 關鍵字修飾的是方法,起宣告作用,告訴 JVM 老哥自己去呼叫這個方法。 這個方法的實現在別的語言那裡已經實現,我們是看不到原始碼的。

初始化

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

原始碼裡面一個靜態塊,一個靜態方法和一個沒有顯示的預設構造方法,沒有成員變數。可以看出來 registerNatives() 方法只會被呼叫一次。

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);
}

該方法可以被重寫,主要用來判斷兩個物件是否相等。

該方法有一些約定。

  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 { }

當垃圾回收器確定不再有對該物件的引用時,由垃圾回收器在物件上呼叫該方法。該方法只會被呼叫一次。

參考

如果我的文章幫助到您,可以關注我的微信公眾號,第一時間分享文章給您

相關推薦

真的瞭解Object原始碼

歡迎點贊閱讀,一同學習交流,有疑問請留言 。 GitHub上也有開源 JavaHouse 歡迎star 引入 Object 應該是比較簡單的原始碼了。現在我們來分析一下他。Object 是類層次結構的根。Java體系裡面的每個類預設都有一個超類就是 Object。總之,所有物件,包含陣列,都預設實現該類的

校園網路安全CTF 第一題 和 瞭解

第一題: 需要先找到相應頭(REsponse header中的tips)   <?php$flag = "***";if (isset($_GET['repo']))//檢測變數是否設定 { if (strcmp($_GET['repo'], $flag) == 0) //比較兩個

真的瞭解[super ]關鍵字

前言 此篇文章是看了阮老師的es6教程,看到super關鍵字的時候覺得有必要總結梳理一下,原文還是參考 ECMAScript 6入門。 正文 super 這個關鍵字,既可以當作函式使用,也可以當作物件使用。 1.當作函式使用 super作為函式呼叫時,代表父類的建構函式。ES6 要

真的瞭解新媒體?黎想將淺談一個成功的新媒體所必須具備的基本要素?

在正式介紹前,為了幫助大家更好的瞭解新媒體,避免認識上的誤區。藝形藝意工作室創始人、騰訊網、百度網、搜狐網知名專欄作者黎想將首先教你用一招輕鬆區別的方法: 新媒體涵蓋了所有數字化的媒體形式,包括所有數字化的傳統媒體、網路媒體、移動端媒體、數字電視、數字報刊雜誌等;自媒體是基於擁有眾多粉絲

Java中執行緒池,真的瞭解會用

在《 深入原始碼分析Java執行緒池的實現原理 》這篇文章中,我們介紹過了Java中執行緒池的常見用法以及基本原理。 在文中有這樣一段描述: 可以通過Executors靜態工廠構建執行緒池,但一般不建議這樣使用。 關於這個問題,在那篇文章中並沒有深入的展開。作者之所以這

遇見未來 | 讀完這篇文章,真的瞭解超融合

超融合的概念自2012年被提出到現在,經歷了6年的時間。其技術已經從最初的以儲存的融合為重點,經歷過計算、儲存、網路的全面融合,到現在,重心落在雲端計算平臺的交付,整個技術趨於成熟。   今天我們有幸邀請到青雲QingCloud青立方產品總監廖洋(Lester)老師,請

真的瞭解volatile關鍵字

一、Java記憶體模型想要理解volatile為什麼能確保可見性,就要先理解Java中的記憶體模型是什麼樣的。Java記憶體模型規定了所有的變數都儲存在主記憶體中。每條執行緒中還有自己的工作記憶體,執行緒的工作記憶體中儲存了被該執行緒所使用到的變數(這些變數是從主記憶體中拷貝

真的瞭解Instant Run

在Instant Run剛出來的時候,反編譯原始碼寫過一篇Instant Run原理解析,但過於基於原始碼,感覺沒有寫清楚,這周Android Developers推出了Instant Run: An Android Tool Time Deep Dive來講解Inst

Android Studio新功能解析,真的瞭解Instant Run

轉載請註明出處:http://blog.csdn.net/guolin_blog/article/details/51271369 本篇文章首發於我的微信公眾號,由於網上講解Android Studio中Instant Run功能的文章實在是太少了,為了讓更多

真的瞭解計算機除法

前不久看了《C++反彙編與逆向分析技術揭祕》看到除法的介紹部分,裡面有1道題,8 % -3 = ?;-8 % -3 = ?;-8 % 3 = ?;大家能答的上來嗎?反正我當時是沒答上來,我想肯定很多人也一時答不上來,下面是上題的答案:               8 % -

深入淺出ES6(一):真的瞭解箭頭函式

前言 這個系列主要是說明ES6的新特性,從2015年到現在,es6出來也有挺長一段時間了,在專案中也在普遍使用這些特性.,網上的寫es6的文章也大把, 但我感覺可能還是停留在會用的階段,,至於為什麼要這麼用, 又為什麼會出現這個特性,解決了什麼樣的問題,這些都

真的瞭解分層架構?——寫給被PetShop"毒害"的朋友們

一葉障目 .NET平臺上的分層架構(很多朋友稱其為“三層架構”),似乎是一個長盛不衰的話題。經常看到許多朋友對其進行分析、探討、辯論甚至是抨擊。筆者在仔細閱讀了大量這方面文章後,認為許多朋友在分層架構的理解上存在兩個比較大的偏頗: 1.沒有從本質角度去理解分層的內涵,而只

真的瞭解Android ListView

什麼是Android ListView? ListView是一個顯示可滾動的專案列表檢視組。 該列表中的專案使用的是自動插入到列表Adapter ,拉從源內容,如陣列或資料庫查詢,把每個專案導如成被放置到列表的檢視。 在android開發中ListView是

真的瞭解模運算?

問題 假設我們需要編寫一個字母表右移對映的程式(可能用於實現某種加密演算法),說起來似乎有些抽象,舉個例子便清晰了: 譬如字母表為 { ‘a’, ‘b’, ‘c’, ‘d’, ‘e’ }, 右移3位的話, 字母表便被對映為 { ‘d’, ‘e’, ‘a’,

真的瞭解單例

    又到了一個老生常談的話題,單例模式,可能在面試時我們也經常會遇到,但是看似很簡單的問題,卻能看出一個人對單例理解的深度。要寫一個單例,首先需要讓構造器私有,還需要對外提供一個可以獲取單例的一個入口,通常我們可能會這樣寫:第一種:public class SingleT

真的瞭解Grid佈局

Grid網格佈局 概述:Grid將容器劃分為一個個網格,通過任意組合不同的網格,做出你想想要的佈局 Grid與flex佈局相似,將整個Grid分為了容器與子項(格子)   Grid容器的三個重要的概念: 行和列 單元格 網格線   行和列 行和列的概念和柵格系統的的概念相似 單元格在水

JavaScript 真的瞭解this指向

JavaScript 你真的瞭解this指向嗎 前言   終於開始寫this指向了,相信這對很多JavaScript的學習者來說是一個非常恐怖的環節,個人認為也算是JavaScript中最難理解的一個知識點,this非常的方便但是在你不熟悉它的情況下可能會出現很多坑。   本篇文章將帶你充分了解this指

真的瞭解串列埠(示波器串列埠波形分析)

串列埠是最常用的外設了,串列埠基本都是微控制器的標配。串列埠通訊只需要3條線組成,分別為RX、TX、GND。下面將重點分析串列埠資料幀組成。 一、    串列埠通訊幀  串列埠通訊幀資料如此,每幀由空閒位、起始位、資料位、校驗位、停止位組成 傳輸的資料是低位在前高位

線程池不來了解一下

java並發編程 新建 out 沒有 在線 dex keepal AD 定性 前言 只有光頭才能變強 回顧前面: ThreadLocal就是這麽簡單 多線程三分鐘就可以入個門了! 多線程基礎必要知識點!看了學習多線程事半功倍 Java鎖機制了解一下 AQS簡簡單單過一

OTA近場測量真的瞭解?

如果你在百度搜索OTA,排在最上面的一定是線上旅遊,可是對於我們射頻工程師來說,OTA就別有一番意思了 我們一起來看一下 今日份重點: 1.近場測量技術及場地的發展 2.近場測量的分類 3.現今主流近場多探頭OTA系統簡介 4.小結 1.近場測量技術及場地的發展 近場測量的理論基