個人測試:
1.
Class c = staticPack.Word.class;
與 Class.forName("staticPack.Word",false,off.getClass().getClassLoader());
結果一致,顯示結果爲:
Loaded Office
類別準備載入
類別準備實例化
Word static initialization!
2.
Class c = Class.forName("staticPack.Word");
與 Class.forName("staticPack.Word",true,off.getClass().getClassLoader());
結果一致,顯示結果爲:
Loaded Office
類別準備載入
Word static initialization!
類別準備實例化
3.異常報錯,顯示調用的類
3.1 Class c = Class.forName("staticPack.Word",true,off.getClass().getClassLoader());
在Word。java中報錯
static{
String a = null;
System.out.println(a.equals("")+"Word static initialization!");
}
顯示錯誤信息:
Loaded Office
類別準備載入
Exception in thread "main" java.lang.ExceptionInInitializerError
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Unknown Source)
at staticPack.Office.main(Office.java:13)
Caused by: java.lang.NullPointerException
at staticPack.Word.<clinit>(Word.java:7)
... 3 more
說明沒有調用默認調用了Class。forName()這個方法
3.2 Class c = Class.forName("staticPack.Word2",false,off.getClass().getClassLoader());
顯示錯誤信息:
Loaded Office
類別準備載入
類別準備實例化
Exception in thread "main" java.lang.ExceptionInInitializerError
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
at java.lang.reflect.Constructor.newInstance(Unknown Source)
at java.lang.Class.newInstance0(Unknown Source)
at java.lang.Class.newInstance(Unknown Source)
at staticPack.Office.main(Office.java:17)
Caused by: java.lang.NullPointerException
at staticPack.Word.<clinit>(Word.java:7)
... 7 more
出錯信息是在調用newInstance0的時候出錯,要是沒有調用。程序正常運行。只是加載了類的信息。
總結:
那說明了靜態塊,只是在調用newInstance0方法時候纔會去觸發。
========================================================
"java深度歷險"一書在講解“類裝載”的一章中,舉了以下的例子:
- public interface Assembly{
- public void start();;
- }
- public class Word implements Assembly{
- static{
- System.out.println("Word static initialization!");;
- }
- public void start();{
- System.out.prinlnt("Word starts");;
- }
- }
- public class Office{
- public static void main(String args[]); throws Exception{
- Office off = new Office();;
- System.out.println("類別準備載入");;
- Class c = Class.forName(args[0],true,off.getClass();.getClassLoader(););;
- System.out.println("類別準備實例化");;
- Object o = c.newInstance();;
- Object o2= c.newInstance();;
- }
- }
public interface Assembly{
public void start();;
}
public class Word implements Assembly{
static{
System.out.println("Word static initialization!");;
}
public void start();{
System.out.prinlnt("Word starts");;
}
}
public class Office{
public static void main(String args[]); throws Exception{
Office off = new Office();;
System.out.println("類別準備載入");;
Class c = Class.forName(args[0],true,off.getClass();.getClassLoader(););;
System.out.println("類別準備實例化");;
Object o = c.newInstance();;
Object o2= c.newInstance();;
}
}
執行java Office Word,運行結果如下:“Loaded Office”
“類別準備載入”
“Loaded Accembly”
“Loaded Word””
“Word static initialization”
“類別準備實體化”。
但是如果將Office.java中Class.forName(args[0],true,off.getClass().getClassLoader())中的true變爲false,再執行java Office Word結果顯示爲:
“Loaded Office”
“類別準備載入”
“Loaded Accembly”
“Loaded Word””
“類別準備實體化”
“Word static initialization”。
顯然兩次紅字部分順序相反,及static塊執行的順序不同。此書作者提出了原因,原文:
其實,該書作者的上述描述有誤。通過一個試驗,就可以看出謬誤所在。
- public class TestA{
- static{
- System.out.println("Static block executed!");;
- }
- }
- public class Test{
- public static void main(String args[]);{
- Test test = new Test();;
- Class.forName("TestA",true,test.getClass();.getClassLoader(););;
- }
- }
public class TestA{
static{
System.out.println("Static block executed!");;
}
}
public class Test{
public static void main(String args[]);{
Test test = new Test();;
Class.forName("TestA",true,test.getClass();.getClassLoader(););;
}
}
運行一下,相信大家一定可以看到,“Static block executed!”的輸出。這與
的說法矛盾。
其實我想事實是這樣的:
一個類的運行,JVM做會以下幾件事情 1、類裝載 2、鏈接 3、初始化 4、實例化;而初始化階段做的事情是初始化靜態變量和執行靜態方法等的工作。所以,當Class.forName(args[0],true,off.getClass().getClassLoader());中的true變爲false的時候,就是告訴JVM不需再load class之後進行initial的工作。這樣,將initial的工作推遲到了newInstance的時候進行。所以,static塊的絕對不是什麼“只是在類被第一次實體化的時候纔會被僅僅調用一次”,而應該是在類被初始化的時候,僅僅調用一次。