个人测试:
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();;
- }
- }
“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(););;
- }
- }
运行一下,相信大家一定可以看到,“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块的绝对不是什么“只是在类被第一次实体化的时候才会被仅仅调用一次”,而应该是在类被初始化的时候,仅仅调用一次。