類初始化與類對象初始化

來源:互聯網
上載者:User

類的生命週期:

載入——> 驗證、準備、解析——>初始化——>使用——>卸載

類初始化進行的5種情況:

1.遇到new、getstatic、putstatic或invokestatic這4條位元組碼指令時,如果類沒有進行過初始化,則需要先觸發其初始化。產生這4條指令的最常見的java代碼情境是:使用new關鍵字執行個體化對象的時候、讀取或者設定一個類的靜態欄位(被final修飾的除外),以及調用一個類的靜態方法

2.使用java.lang.reflect包的方法對類進行反射調用的時候,如果類沒有初始化過,則需要先觸發其初始化

3.當初始化一個類的時候,如果發現其父類還沒有進行初始化,則需要先觸發其父類的初始化

4.當虛擬機器啟動時,虛擬機器初始化一個main方法的類

5.當使用jdk1.7的動態語言支援時,如果一個java.lang.invoke.MethodHandler執行個體後的解析結果REF_getStatic、REF_putstaic、REF_involeStatic的方法控制代碼,並且這個方法控制代碼所對應的類沒有進行初始化,則需要先觸發其初始化


類初始化階段是執行類構造器<clinit>()方法的過程。

<clinit>()方法是由編譯器自動收集類中的所有類變數的賦值動作和靜態語句塊(static{}塊)中的語句合并產生的,編譯器收集的順序是由語句在源檔案中出現的順序所決定的,靜態語句塊中只能訪問到定義在靜態語句之前的變數,定義在它之後的變數,在前面的靜態語句塊可以賦值,但是不能訪問。

<clinit>方法與類的建構函式(或者說執行個體構造器<init>()方法)不同,它不需要顯示得調用父類構造器,虛擬機器會保證在子類的<clinit>()方法執行之前,父類的<clinit>()方法已經執行完畢。

由於父類的<clinit>()方法先執行,也就意味著父類中定義的靜態語句塊要優先於子類的變數賦值操作。

<clinit>()方法對於類或介面來說並不是必需的,如果一個類中沒有靜態語句塊,也沒有類變數,那麼編譯器可以不為這個類生產<clinit>()方法

介面中不鞥使用靜態語句塊,但仍然有變數初始化的賦值操作,因此介面與類一樣都會產生<clinit>()方法,但介面與類不同的是,執行介面的<clinit>()方法不需要先執行父介面的<clinit>()方法。只有當父介面中定義的變數使用時,父介面才會初始化。另外,介面的實作類別在初始化時也一樣不會執行介面的<clinit>()方法。

虛擬機器會保證一個類的<clinit>()方法在多線程環境中被正確地加鎖、同步,如果多個線程同時去初始化一個類,哪兒只會有一個線程去執行這個類的<clinit>方法,其他線程都需要阻塞等待,知道活動線程執行clinit()方法完畢。如果一個類的<clinit>()方法有耗時很長的操作,就可能造成多一個進程阻塞。

聯繫我們

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