Java的靜態代碼塊是否會在類被加載時自動執行?


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類加載的過程

  1. 裝載
  2. 連接
  3. 初始化

    其中裝載階段又三個基本動作組成:

  1.     通過類型的完全限定名,產生一個代表該類型的二進制數據流
  2.     解析這個二進制數據流為方法區內的內部數據結
  3.     構創建一個表示該類型的java.lang.Class類的實例

    另外如果一個類裝載器在預先裝載的時遇到缺失或錯誤的class文件,它需要等到程序首次主動使用該類時才報告錯誤。

 

    連接階段又分為三部分:

  1. 驗證,確認類型符合Java語言的語義,檢查各個類之間的二進制兼容性(比如final的類不用擁有子類等),另外還需要進行符號引用的驗證。
  2. 准備,Java虛擬機為類變量分配內存,設置默認初始值。
  3. 解析(可選的) ,在類型的常量池中尋找類,接口,字段和方法的符號引用,把這些符號引用替換成直接引用的過程。

 當一個類被主動使用時,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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM