在java中除了使用構造器類對單個對象進行初始化操作外,我們還可以通過初始化塊來實現。在一個類中可以有多個初始化塊,相同類型的初始化塊之間有順序:前面定義的初始化塊先執行,后面定義的初始化塊后執行。使用static修飾的初始化塊,稱為靜態初始化塊,在初始化塊中可以定義局部變量、調用其他對象的方法,以及使用分支、循環語句等。
靜態初始快:執行優先級高于非靜態初始塊,它會在對象裝載到系統的時候執行一次,執行完成便銷毀,它僅能初始化類變量,即static修飾的數據成員。
非靜態初始化塊:執行的時候如果有靜態初始化塊,先執行靜態初始化塊再執行非靜態初始化塊,在每個對象生成時都會被執行一次,它可以初始化類的實例變量。非靜態初始化塊會在構造函數執行時,在構造函數主體代碼執行之前被運行。
下面程序就定義了初始化塊:
class Person { { int num = 25; System.out.PRintln("普通初始塊1"); } static { int num = 45; System.out.println("靜態初始塊1"); } { int num = 25; System.out.println("普通初始塊2"); } public Person() { System.out.println("無參構造器"); }}public class MainTest { public static void main(String[] args) { new Person(); }}輸出結果如下:
靜態初始塊1普通初始塊1普通初始塊2無參構造器從運行結果來看,當創建Java對象時,系統總是先調用靜態初始化塊,之后按順序執行普通初始化塊,最后才執行構造器。靜態初始化塊是類相關的,用于對整個類進行初始化處理,靜態初始化塊也被稱為類初始化塊,也屬于類的靜態成員,因此不能訪問非靜態成員。
最后值得指出的是:當JVM第一次主動使用某個類時,系統會在類準備階段為該類的所有靜態Field分配內存,在初始化階段負責初始化這些靜態Field,初始化靜態Field就是執行類初始化代碼或者聲明類Field時指定的初始值。
首先有三個概念需要了解:
一、靜態初始化:是指執行靜態初始化塊里面的內容。
二、實例初始化:是指執行實例初始化塊里面的內容。
三、構造方法:一個名稱和類的名稱一樣的方法,特殊在于不帶返回值。
我們先來看看一段程序結果:
public class Book { public static int booksum = 0; // 靜態變量 static { // 這是靜態初始化塊 print(); System.out.println("this is static block"); } { // 實例初始化塊 System.out.println("初始化塊:" + booksum); } public Book() { // 構造方法 System.out.println("this is Book's constructor"); booksum += 1; } public static void print() { // 靜態方法 System.out.println("this is static method"); } public static void main(String[] args) { // Book book = new Book(); }}執行結果:
this is static methodthis is static block去掉main方法中的注釋,運行結果為:
this is static methodthis is static block初始化塊:0this is Book's constructor總結:
僅從代碼執行的角度來探討Java加載類、創建對象的過程,并沒有深入到JVM的機制中去。
1.一個對象第一次創建的時候,先要加載該對象所屬的類,即對應的.class文件,當然如果類已經加載,再次創建該類的對象時,就不再需要重新加載類了。而一個類加載的時候,有三個部分需要加載,一個是靜態變量,再然后是靜態方法,然后是靜態初始化塊。(見到第一次執行結果就知道了,由于沒有創建實例所以初始化塊不執行)
2.然后開始創建該類的實例了,當然如果靜態方法跟靜態初始化塊中有對象的創建時,就繼續加載該對象的類,當然已經加載了該對象的類的話就不需要再次加載了。那么對象實例的創建過程是什么呢?首先是成員變量的引入,然后是實例初始化塊,之后才是構造方法,構造方法執行完成后才算把這個對象給創建出來了。
在這個過程中,真正可以編寫執行代碼的有三個地方,靜態初始化塊、實例初始化塊以及構造方法塊。從以上的分析中我們可以看到,這三個代碼塊的執行順序是”先類的靜態初始化塊,再實例初始化塊,最后是執行構造方法塊。也就是說,靜態初始化是屬于類加載的過程,所以它執行一次,而實例初始化是每個對象創建時都會執行一次,而構造方法跟實例初始化塊其實差不多,不過它在實例初始化塊之后執行,而且構造方法可以重載多個,執行哪個構造方法是根據你的選擇來的。
看下面的代碼運行結果也可得出上面的結論:
public static void main(String[] args) { Book book1 = new Book(); Book book2 = new Book(); }執行結果如下所示:
this is static methodthis is static block初始化塊:0this is Book's constructor初始化塊:1this is Book's constructor
新聞熱點
疑難解答