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關鍵子來呼叫父類帶引數的構造方法,否則編譯不能通過。