java類的初始化和建構函式

來源:互聯網
上載者:User

標籤:java   類載入   初始化   建構函式   

本人小白一枚,看java類的初始化的時候好暈的說,我覺著書上雖然說的對,但總覺得有些資訊沒說出來,沒說清楚,看了好多文章部落格的,現在有些感悟,來小寫下總結,也算是為以後再次複習種個好果子。

先摘一下書上寫的:

載入:將類的class檔案讀入記憶體,並為之建立一個java.lang.class對象。

串連:把類的位元據合并到JRE中,檢查被載入的類是否有正確的內部結構,並和其他類協調一致。為類的靜態FIELD分配記憶體,設定預設值,將類的位元據中的符號引用替換成直接引用。

初始化:主要對靜態Field進行初始化,初始化方式兩種:聲明靜態Field時指定的值,使用靜態初始化塊為其指定初始值。JVM會按他們的順序執行。初始化包括以下步驟:
 假設該類沒有被載入和串連,則先載入並串連該類。
 假設他的父類沒有被初始化,則先初始化他的父類
 假設類中有初始化語句,則系統依次執行。

看完之後我腦子裡一直就盤旋著幾個問題:

    1、類的載入和初始化神馬的和建構函式有啥關係和區別?

    2、類的初始化會為執行個體屬性分配記憶體嗎?

    3、如果我要建立一個執行個體對象,到底是怎麼個建立流程?

OK,如果你也有以上的疑問,那麼我們一起來看看到底是怎麼回事!我會直接回答最後一個問題,當你把這個問題弄明白了,前面的就迎刃而解了。

  public class Person{

  static{staticInt = 6; }

  {vInt =15;  }

   static int staticInt = 3;

   int vInt = 10;

   Person(){

    staticInt = 9;

     vInt = 20;

    }

}

    Person  p = new Person();

JVM會看:

1)哎,有個變數p,然後就給它分配一個空間(這裡的空間指的是指標,而不是實際的對象)

2)分完了以後發現它需要Person這個類來進行執行個體化,然後就到記憶體裡找,看這個類有沒有被載入到記憶體裡來,如果有救直接用了,如果沒有就會進行載入。我們就來說沒有的情況

3)載入的時候,將類的class檔案讀入記憶體,並為之建立一個java.lang.class對象。這裡需要重點說一下,在建立這個對象的時候,就會儲存這個類的所有資訊,比如這個類有哪些屬性(靜態非靜態都包括),有哪些方法(靜態非靜態都包括),有什麼代碼塊,都會被記錄。

4)把類的位元據合并到JRE中,檢查被載入的類是否有正確的內部結構,並和其他類協調一致。JVM跑到java.lang.class對象裡看看,都有啥靜態變數,為他們分配記憶體,設定預設值,將類的位元據中的符號引用替換成直接引用。

5)然後對靜態Field進行初始化,初始化方式兩種:聲明靜態Field時指定的值,使用靜態初始化塊為其指定初始值。JVM會按他們的順序執行。這個地方需要注意:如上代碼,靜態變數staticInt最後會被賦值為3,因為靜態代碼塊在聲明之前。JVM是先跑到java.lang.class對象看有什麼靜態變數,給他分個空間,然後再執行的聲明和靜態代碼塊語句,因此初始化之後值為3.

好了,345都是類的載入和初始化,我們再來看看都做了些什麼:產生java.lang.class對象,有該類裡的屬性方法代碼塊的所有資訊。再為靜態屬性分配了記憶體並執行了靜態代碼塊,按

順序把靜態屬性給初始化了。這裡並沒有為非靜態屬性分配記憶體,也沒有執行建構函式和非靜態代碼塊,一句話

總結就是:記錄下這個類的所有屬性和方法代碼塊等資訊,為靜態變數分記憶體並賦值

初始化之後,現在JVM改根據這個初始化好的類資訊來進行執行個體化了。先前被初始化好的靜態變數會被所有執行個體共用,靜態代碼塊將不會再被執行,相當於失效了。我們來看看JVM接下來要幹嘛?

6)JVM跑到java.lang.class對象裡看一看,有哪些執行個體變數需要分配記憶體的,跟靜態變數類似的,JVM先給執行個體變數分記憶體,分完之後,執行代碼塊和聲明,在這裡vInt為10。

7)最後執行建構函式,執行完後,vInt變成了20,staticInt變成了9,然後改建構函式隱性的返回一個Person執行個體對象給變數p。     

好了,講完了,我們再看看12問題

1、類的載入和初始化神馬的和建構函式有啥關係和區別?

只要在類需要執行個體化的時候才會執行建構函式。而類的載入和初始化卻在這些情況都會被執行:建立執行個體  調用靜態方法  訪問某個靜態Field(如果該變數還是final的,則在編譯階段就能確定下來,就不會初始化)   初始化某個類子類

2、類的初始化會為執行個體屬性分配記憶體嗎?

不會為執行個體屬性分配,只有在執行個體化的時候才會分記憶體

總結

1)將類的class檔案讀入記憶體,並為之建立一個java.lang.class對象。

2)把類的位元據合并到JRE中,檢查被載入的類是否有正確的內部結構,並和其他類協調一致,並為靜態變數分記憶體

3)為靜態變數初始化賦值

以上為初始化順序

4)為非靜態變數分記憶體,並賦值

5)建構函式,返回構造好的對象


如果有子類父類別關係的時候:

父類和子類的class檔案都載入到記憶體,當父類,和子類有Static時,先初始化Static,再初始化子類的Static,

再初始化父類的其他成員變數->父類構造方法->子類其他成員變數->子類的構造方法。

有不對的地方還望高手指出啊


著作權聲明:本文為博主原創文章,未經博主允許不得轉載。

java類的初始化和建構函式

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.