JAVA靜態代碼塊會在類被載入時自動執行? 一、先看Java靜態方法,靜態變數 http://www.cnblogs.com/winterfells/p/7906078.html 靜態代碼塊 在類中,可以將某一塊代碼聲明為靜態的,這樣的程式塊叫靜態初始化段。靜態代碼塊的一般形式如下: 編譯通過後,用 ...
JAVA靜態代碼塊會在類被載入時自動執行?
一、先看Java靜態方法,靜態變數
http://www.cnblogs.com/winterfells/p/7906078.html
靜態代碼塊
在類中,可以將某一塊代碼聲明為靜態的,這樣的程式塊叫靜態初始化段。靜態代碼塊的一般形式如下:
static { 語句序列 }
public class staticBlock{ //定義一個普通的main()方法 public static void main(String args[]){ System.out.println("This is main method."); } //定義一個靜態代碼塊 static{ System.out.println("This is static block."); int stVar = 0; //這是一個局部變數,只在本塊內有效 } }
編譯通過後,用java命令載入本程式,會得到如下輸出:
This is static block.
This is main method.
從以上輸出結果中可以看出,靜態代碼塊甚至在main方法之前就被執行。在main()方法中可以完成的任務在靜態代碼塊中都可以完成。但是二者在執行上仍然有一些區別,main方法是整個程式啟動的入口,而靜態代碼塊是存在於某個類中的一個過程。
那是不是只要類被載入了就一定會執行靜態代碼塊?
二、再看JVM類載入的過程
- 裝載
- 連接
- 初始化
其中裝載階段又三個基本動作組成:
- 通過類型的完全限定名,產生一個代表該類型的二進位數據流
- 解析這個二進位數據流為方法區內的內部數據結
- 構創建一個表示該類型的java.lang.Class類的實例
另外如果一個類裝載器在預先裝載的時遇到缺失或錯誤的class文件,它需要等到程式首次主動使用該類時才報告錯誤。
連接階段又分為三部分:
- 驗證,確認類型符合Java語言的語義,檢查各個類之間的二進位相容性(比如final的類不用擁有子類等),另外還需要進行符號引用的驗證。
- 準備,Java虛擬機為類變數分配記憶體,設置預設初始值。
- 解析(可選的) ,在類型的常量池中尋找類,介面,欄位和方法的符號引用,把這些符號引用替換成直接引用的過程。
當一個類被主動使用時,Java虛擬就會對其初始化,如下五種情況為主動使用:
1. 遇到new, getstatic, putstatic 或者 invokestatic 4條位元組碼指令時,如果類沒有進行過初始化,則需要先進行初始化。這些場景包括:使用new關鍵字實例化對象,讀取或者設置一個類的靜態欄位以及調用一個類的靜態方法的時候。
2. 使用java.lang.reflect包的方法進行反射調用的時候,如果類沒有初始化,需要進行初始化。
3. 當初始化一個類的時候發現其父類還沒有初始化,需要對父類進行初始化。
4. JVM啟動時,用戶指定的包含main方法的那個類,需要首先進行初始化。
5. JDK1.7中動態語言的支持,解析java.lang.invoke.MethodHandle的結果為REF_getStatic, REF_putStatic, REF_invokeStatic方法的句柄時,對應的類沒有初始化的時候。
實際上,static塊的執行發生在“初始化”的階段。初始化階段,jvm主要完成對靜態變數的初始化,靜態塊執行等工作。
下麵我們看看執行static塊的幾種情況:
1、第一次new A()的過程會列印"";因為這個過程包括了初始化
2、第一次Class.forName("A")的過程會列印"";因為這個過程相當於Class.forName("A",true,this.getClass().getClassLoader());
3、第一次Class.forName("A",false,this.getClass().getClassLoader())的過程則不會列印""。因為false指明瞭裝載類的過程中,不進行初始化。不初始化則不會執行static塊。
再看這個例子
class MyClass1 { static {//靜態塊 System.out.println("static block "); } } public class Main { Class[] classArray = { MyClass1.class//這樣引用該類,必然需要將該類載入到虛擬機中,(反射機制) }; public static void main(String[] args){ System.out.println("hello word"); } }
結果:
hello world
所以結論是不初始化則不會執行static塊。
參考:《深入理解java虛擬機》
http://blog.csdn.net/jiese1990/article/details/40154329
http://www.cnblogs.com/ivanfu/archive/2012/02/12/2347817.html