1. 程式人生 > >Java靜態程式碼塊和靜態方法的區別/類載入順序

Java靜態程式碼塊和靜態方法的區別/類載入順序


 (一)java 靜態程式碼塊 靜態方法區別
 一般情況下,如果有些程式碼必須在專案啟動的時候就執行的時候,需要使用靜態程式碼塊,這種程式碼是主動執行的;需要在專案啟動的時候就初始化,在不建立物件的情況下,其他程式來呼叫的時候,需要使用靜態方法,這種程式碼是被動執行的. 靜態方法在類載入的時候 就已經載入 可以用類名直接呼叫
 比如main方法就必須是靜態的 這是程式入口
 兩者的區別就是:靜態程式碼塊是自動執行的;
 靜態方法是被呼叫的時候才執行的.
 
 靜態方法
 (1)在Java裡,可以定義一個不需要建立物件的方法,這種方法就是靜態方法。要實現這樣的效果,只需要在類中定義的方法前加上static關鍵字。例如:
 
 public static int maximum(int n1,int n2)
 
 使用類的靜態方法時,注意:
 
 a在靜態方法裡只能直接呼叫同類中其他的靜態成員(包括變數和方法),而不能直接訪問類中的非靜態成員。這是因為,對於非靜態的方法和變數,需要先建立類的例項物件後才可使用,而靜態方法在使用前不用建立任何物件。
 
 b 靜態方法不能以任何方式引用this和super關鍵字,因為靜態方法在使用前不用建立任何例項物件,當靜態方法呼叫時,this所引用的物件根本沒有產生。
 
 (2)靜態變數是屬於整個類的變數而不是屬於某個物件的。注意不能把任何方法體內的變數宣告為靜態,例如:
 fun()
 {
 static int i=0;//非法。
 }
 
 (3)一個類可以使用不包含在任何方法體中的靜態程式碼塊,當類被載入時,靜態程式碼塊被執行,且只被執行一次,靜態塊常用來執行類屬性的初始化。例如:
 static
 {
 }
 
 類裝載步驟
 在Java中,類裝載器把一個類裝入Java虛擬機器中,要經過三個步驟來完成:裝載、連結和初始化,其中連結又可以分成校驗、準備和解析三步,除了解析外,其它步驟是嚴格按照順序完成的,各個步驟的主要工作如下:
 
 裝載:查詢和匯入類或介面的二進位制資料;
 連結:執行下面的校驗、準備和解析步驟,其中解析步驟是可以選擇的;
 校驗:檢查匯入類或介面的二進位制資料的正確性;
 準備:給類的靜態變數分配並初始化儲存空間;
 解析:將符號引用轉成直接引用;
 初始化:啟用類的靜態變數的初始化Java程式碼和靜態Java程式碼塊。
 初始化類中屬性是靜態程式碼塊的常用用途,但只能使用一次。
 
 (二)靜態程式碼塊的初始化順序
  class Parent{ 
  static String name = "hello"; 
  { 
  System.out.println("parent block"); 
  } 
  static { 
  System.out.println("parent static block"); 
  } 
  public Parent(){ 
  System.out.println("parent constructor"); 
  } 
  } 
  
  class Child extends Parent{ 
  static String childName = "hello"; 
  { 
  System.out.println("child block"); 
  } 
  static { 
  System.out.println("child static block"); 
  } 
  public Child(){ 
  System.out.println("child constructor"); 
  } 
  } 
  
  public class StaticIniBlockOrderTest { 
  
  public static void main(String[] args) { 
  new Child();//語句(*) 
  } 
  }


問題:當執行完語句(*)時,列印結果是什麼順序?為什麼?

 解答:當執行完語句(*)時,列印結果是這樣一個順序 :
  parent static block
 child static block
 parent block
 parent constructor
 child block

 child constructor

 分析:當執行new Child()時,它首先去看父類裡面有沒有靜態程式碼塊,如果有,它先去執行父類裡面靜態程式碼塊裡面的內容,當父類的靜態程式碼塊裡面的內容執行完畢之後,接著去執行子類(自己這個類)裡面的靜態程式碼塊,當子類的靜態程式碼塊執行完畢之後,它接著又去看父類有沒有非靜態程式碼塊,如果有就執行父類的非靜態程式碼塊,父類的非靜態程式碼塊執行完畢,接著執行父類的構造方法;父類的構造方法執行完畢之後,它接著去看子類有沒有非靜態程式碼塊,如果有就執行子類的非靜態程式碼塊。子類的非靜態程式碼塊執行完畢再去執行子類的構造方法,這個就是一個物件的初始化順序。
 
 總結:
 物件的初始化順序:首先執行父類靜態的內容,父類靜態的內容執行完畢後,接著去執行子類的靜態的內容,當子類的靜態內容執行完畢之後,再去看父類有沒有非靜態程式碼塊,如果有就執行父類的非靜態程式碼塊,父類的非靜態程式碼塊執行完畢,接著執行父類的構造方法;父類的構造方法執行完畢之後,它接著去看子類有沒有非靜態程式碼塊,如果有就執行子類的非靜態程式碼塊。子類的非靜態程式碼塊執行完畢再去執行子類的構造方法。總之一句話,靜態程式碼塊內容先執行,接著執行父類非靜態程式碼塊和構造方法,然後執行子類非靜態程式碼塊和構造方法。

 
 注意:子類的構造方法,不管這個構造方法帶不帶引數,預設的它都會先去尋找父類的不帶引數的構造方法。如果父類沒有不帶引數的構造方法,那麼子類必須用supper關鍵子來呼叫父類帶引數的構造方法,否則編譯不能通過。