Java中經常有一些靜態塊,這是用來在生成類之前進行的初始化,無論java還C++語言中的static,都是最先初始化好的。結構如下:
static {
靜態語句代碼塊
}
{
非靜態語句代碼塊
}
異同點
相同點:都是在JVM加載類時且在構造方法執行之前執行,在類中都可以定義多個,一般在代碼塊中對一些static變量進行賦值。
不同點:靜態代碼塊在非靜態代碼塊之前執行(靜態代碼塊-->非靜態代碼塊-->構造函數)。
靜態代碼塊只在第一次new(或者只要訪問了就)執行一次,之後不在執行,而非靜態代碼塊在每new一次都會執行一次,跟構造函數一樣。非靜態代碼塊可以在普通方法中定義(個人感覺作用不大);而靜態代碼塊不行。
Java代碼
public class TestStatic { static { System.out.println("基類 Static 靜態語句塊"); } public TestStatic() { System.out.println("基類 默認無參構造器"); } { System.out.println("基類 非靜態語句塊"); } public static void Iint() { System.out.println("基類 Static Iint"); } }
public class User extends TestStatic { private static final long serialVersionUID = 1L; public final double i = Math.random();// 每次得到的結果不一樣 private final static int finalID; private static int finalID2; private int finalID3; static { System.out.println("派生類 Static 靜態語句塊"); finalID=1000; } { System.out.println("派生類 非靜態語句塊"); finalID2+=1; finalID3+=1; } /** full constructor */ public User() { System.out.println("派生類 默認無參構造器"); } public static void IintTest() { System.out.println("派生類 Static Iint"); } }
測試語句1
public static void main(String[] args) {
TestStatic.Iint();//User.Iint();
}
}
輸出結果如下:
基類 Static 靜態語句塊
派生類 Static 靜態語句塊
基類 Static Iint
測試說明了靜態代碼塊不管怎麼樣都會被執行,調用基類的靜態方法,派生類的靜態語句塊也都執行了,調用這個User.Iint(); 也是一樣的結果 。
測試語句2
public static void main(String[] args) {
TestStatic.Iint();//User.Iint();
User.IintTest();
}
}
輸出結果如下:
基類 Static 靜態語句塊
派生類 Static 靜態語句塊
基類 Static Iint
派生類 Static Iint
測試說明了 靜態語句塊執行一次,只是調用了派生類的靜態方法被執行了
測試語句3
public static void main(String[] args) {
TestStatic.Iint();//User.Iint();
User.IintTest();
System.out.println(User.finalID);
TestStatic user = new User();
}
}
執行結果如下:
基類 Static 靜態語句塊
派生類 Static 靜態語句塊
基類 Static Iint
派生類 Static Iint
1000
基類 非靜態語句塊
基類 默認無參構造器
派生類 非靜態語句塊
派生類 默認無參構造器
測試說明了 非靜態代碼塊在每new一次都會執行一次,跟構造函數一樣的次數
測試語句4
public static void main(String[] args) {
TestStatic.Iint();//User.Iint();
User.IintTest();
System.out.println(User.finalID);
TestStatic user = new User();
System.out.println();
System.out.println("第二次初始化派生類");
User user2 = new User();
System.out.println();
System.out.println("第三次次初始化基類");
TestStatic user3 = new TestStatic ();
}
執行結果如下:
基類 Static 靜態語句塊
派生類 Static 靜態語句塊
基類 Static Iint
派生類 Static Iint
1000
基類 非靜態語句塊
基類 默認無參構造器
派生類 非靜態語句塊
派生類 默認無參構造器
第二次初始化派生類
基類 非靜態語句塊
基類 默認無參構造器
派生類 非靜態語句塊
派生類 默認無參構造器
第三次次初始化基類
基類 非靜態語句塊
基類 默認無參構造器
測試說明了靜態代碼塊在非靜態代碼塊之前執行(靜態代碼塊-->非靜態代碼塊-->構造函數)。
靜態代碼塊只在第一次new(或者只要訪問了就)執行一次,之後不在執行,而非靜態代碼塊在每new一次都會執行一次,跟構造函數一樣.
小結:
1、靜態代碼塊是在類加載時自動執行的,非靜態代碼塊在創建對象自動執行的代碼,不創建對象不執行該類的非靜態代碼塊。 順序: 靜態代碼塊--》非靜態代碼塊--》類構造函數。
2、在靜態方法裡面只能直接調用同類中其他的靜態成員(包括變量和方法),而不能直接訪問類中的非靜態成員。因為對於非靜態的方法和變量,需要先創建類的實例對象後方可使用,而靜態方法在使用前不用創建任何對象。
3、如果某些代碼必須要在項目啟動時候就執行的時候,我們可以采用靜態代碼塊,這種代碼是主動執行的;需要在項目啟動的時候就初始化,
在不創建對象的情況下,其他程序來調用的時候,需要使用靜態方法,此時代碼是被動執行的。
區別:靜態代碼塊是自動執行的;
靜態方法是被調用的時候才執行的;
作用:靜態代碼塊可以用來初始化一些項目最常用的變量和對象;靜態方法可以用作不創建對象也可以能需要執行的代碼。