一.與靜態方法的比較
一般情況下,如果有些代碼必須在項目啟動的時候就執行的時候,需要使用靜態代碼塊,這種代碼是主動執行的;需要在項目啟動的時候就初始化,在不創建對象的情況下,其他程序來調用的時候,需要使用靜態方法,靜態方法在類加載的時候 就已經加載 可以用類名直接調用 比如main方法就必須是靜態的 這是程序入口。兩者的區別就是:靜態代碼塊是自動執行的; 靜態方法是被調用的時候才執行的。
二.靜態方法注意事項
使用類的靜態方法時,注意:
a.在靜態方法里只能直接調用同類中其他的靜態成員(包括變量和方法),而不能直接訪問類中的非靜態成員。這是因為,對於非靜態的方法和變量,需要先創建類的實例對象后才可使用,而靜態方法在使用前
不用創建任何對象。
b.靜態方法不能以任何方式引用this和super關鍵字,因為靜態方法在使用前不用創建任何實例對象,當靜態方法調用時,this所引用的對象根本沒有產生(this關鍵字只能在方法內部使用,表示對“調用方法的那個對象”的引用)。
靜態變量是屬於整個類的變量而不是屬於某個對象的。注意不能把任何方法體內的變量聲明為靜態,例如: fun() { static int i=0;//非法。 }
三.程序舉例
1 public class TestStaticCon { 2 public static int a = 0; 3 4 static { 5 a = 10; 6 System.out.println("父類的靜態代碼塊在執行a=" + a); 7 } 8 9 { 10 a = 8; 11 System.out.println("父類的非靜態代碼塊在執行a=" + a); 12 } 13 14 public TestStaticCon() { 15 this("a在父類帶參構造方法中的值:" + TestStaticCon.a); // 調用另外一個構造方法 16 System.out.println(a); 17 System.out.println("父類無參構造方法在執行a=" + a); 18 } 19 20 public TestStaticCon(String n) { 21 System.out.println(n); 22 System.out.println(a); 23 24 } 25 26 public static void main(String[] args) { 27 TestStaticCon tsc = null; 28 System.out.println("!!!!!!!!!!!!!!!!!!!!!"); 29 tsc = new TestStaticCon(); 30 } 31 }
運行結果: 父類的靜態代碼塊在執行a=10 !!!!!!!!!!!!!!!!!!!!! 父類的非靜態代碼塊在執行a=8 a在父類帶參構造方法中的值:10 8 8 父類無參構造方法在執行a=8
四.網友提供
1 public class StaticBlock { 2 3 static { 4 System.out.println("靜態塊"); 5 } 6 { 7 System.out.println("構造塊,在類中定義"); 8 } 9 10 public StaticBlock() { 11 System.out.println("構造方法執行"); 12 } 13 14 public static void main(String[] args) { 15 new StaticBlock(); 16 new StaticBlock(); 17 } 18 19 }
靜態塊 構造塊,在類中定義 構造方法執行 構造塊,在類中定義 構造方法執行
五.今天發現的問題
static塊不一定非要寫在所有變量和方法之前。
public class T2{ private static int total = 200; static{ total = 100; System.out.println("static語句塊"); } public static void main(String[] args){ System.out.println(T2.total); System.out.println(T2.total); } }
上面的程序輸出的結果是: static語句塊 100 100 然后把靜態塊寫在靜態變量的前面,編譯運行后的結果是 static語句塊 200 200 這說明static的加載還是有順序的 是根據他們在類中的位置加載的; 可以有多個,位置可以隨便放,它不在任何的方法體內,JVM加載類時會執行這些靜態的代碼塊,如果static 代碼塊有多個,JVM將按照它們在類中出現的先后順序依次執行它們,每個代碼塊只會被執行一次。
結論:靜態代碼塊是在類加載時自動執行的,非靜態代碼塊是在創建對象時自動執行的代碼,不創建對象不執行該類的非靜態代碼塊。且執行順序為靜態代碼塊------非靜態代碼塊----構造函數。
其中讓我疑惑的是“a在父類帶參構造方法中的值:10”,我再想那時候為什么不是8,debug了(F11,不能直接設置斷點然后運行,那樣和直接運行沒區別),發現先進入了無參的構造方法,執行了第一條語句並且切換到了另一個構造方法(不管是不是反正第一句都要執行,此時a還是10,非靜態代碼塊還未執行),提示找不到源,不管是不是這條語句都提示了這個警告(不算錯誤,因為程序繼續正常運行),然后運行了非靜態代碼塊,繼而從有參的構造方法處繼續執行……
今天知道了適應和忍是兩種不同的境界……