類變量和實例變量及其初始化


0.基本概念

  類變量是指java類中的static數據成員,實例變量則是指java類中的非static數據成員。由於類變量不需要創建一個對象即可訪問,而實例變量則必須與一個具體的對象對應,因此類變量和實例變量的初始化時機是不同的。本文主要關注以下3個問題:

  (1)什么時候初始化類變量?什么時候初始化實例變量?

  (2)什么時候會同時初始化類變量和實例變量?

  (3)在(1)、(2)情形下各個類變量和實例變量的初始化順序?

1.類變量初始化

  1.1 類變量初始化方式

  static變量初始化的方式有兩種:定義時初始化和static代碼塊中初始化。如下代碼所示:

1 class A(){  
2    public static int i = 1;//static變量初始化方式一:在定義時初始化
3    static{//static變量初始化方式二:在static代碼塊初始化static變量
4      System.out.println("statci 代碼塊");
5      }    
6  }

  1.2 類變量初始化時機

  根據有無被final關鍵字修飾,類變量的初始化時機不同。被final關鍵字修飾的類變量在編譯時就已經被初始化被放置在常量池中了,而沒有被final修飾的類變量則在該類首次使用時被初始化。特別需要注意的是,類變量只在該類首次使用時被初始化,這意味着類變量只會被初始化一次。

  在下列情形下,如果一個java類中沒有被final修飾的類變量尚未初始化,那么這些沒有被final修飾的類變量將會被初始化:

  (1)訪問該類中沒有被final修飾的類變量時;

  (2)設置該類中沒有被final修飾的類變量時;

  (3)調用該類的static方法。

  1.2 類變量初始化順序

  類變量初始化會遵循以下三個原則:

  (1)在上述3個情形下,首先會初始化該類中所有沒有被final修飾的類變量,然后再執行對應的操作;

  (2)按照代碼中的順序依次執行static變量定義語句和static代碼塊;

  (3)如果該類有父類且父類的類變量沒有初始化,則先初始化父類的類變量;

  (4)如果父類還有父類的話,根據(3)的規則,以此類推。

  根據上述原則,可以確定類變量初始化順序如下:

//沒有繼承的情形
static變量初始化和static代碼塊

//有繼承的情形
1.父類的static變量初始化和static代碼塊
2.子類的static變量初始化和static代碼塊

/*備注:
類變量初始化只有一次,如果某個java類的類變量已經被初始化過了,則上述過程中的類變量初始化將不再執行
*/

 

2.實例變量初始化

  2.1 實例變量初始化方式

  與類變量初始化方式類似,實例變量初始化方式也有兩種:定義時初始化和代碼塊初始化。示例如下:

1  class A(){  
2    public static int i = 1;//實例變量初始化方式一:在定義時初始化
3 
4    {//實例變量初始化方式二:在代碼塊初始化實例變量
5      System.out.println("代碼塊");
6      }    
7  }

  2.2 實例變量初始化時機和順序

  實例變量初始化是在創建該類的對象時進行的,初始化時遵循的原則是:

  (1)按照代碼中的順序依次執行實例變量定義語句和實例變量代碼塊;

  (2)如果創建該類的對象時該類的類變量尚未初始化,則先初始化類變量,再初始化實例變量;

  (3)如果該類有父類的話,則先創建一個父類對象;並且,如果父類類變量沒被初始化時,先初始化父類的類變量,再初始化父類的實例變量,再調用父類的默認構造器;

  (4)如果父類還有父類的話,根據(3)的規則以此類推,一直到根基類。

  根據上述原則易知,實例變量初始化之前可能會先初始化類變量(這是特別需要留意的一點)。初始化順序如下:

//沒有繼承的情形(且該類的類變量未被初始化)
1.static變量初始化和static代碼塊
2.實例變量初始化和實例變量初始化代碼塊
3.構造函數

//有繼承的情形(且該類和父類的類變量未被初始化)
1.父類的static變量初始化和static代碼塊
2.子類的static變量初始化和static代碼塊
3.父類的實例變量初始化和實例變量初始化代碼塊
4.父類的構造函數
5.子類的實例變量初始化和實例變量初始化代碼塊
6.子類構造函數

/*備注:
類變量初始化只有一次,如果某個java類的類變量已經被初始化過了,則上述過程中的類變量初始化將不再執行
*/

3.小結

  大家看完如果還不太明白類變量和實例變量的初始化時機和順序,可以親自去寫一個demo試試,實踐才能出真知嘛!

  在這里,只強調兩點:

  (1)類變量只會初始化一次;

  (2)類變量和實例變量的初始化時機是不同的,類變量初始化在首次使用該類的時候進行,實例變量的初始化在創建該類的每個對象時都會進行。

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM