单纯看标题的话,可能都不知道本博文要讲的什么东西,我是一个实践主义的人,所以还是先用例子来引入吧。
大家不妨看一下下面的例子,然后想一下会输出什么。
/** * * @author Sel * * 2014.4.1 */public class NotInitialization { public static void main(String[] args) { System.out.println(SubClass.value); }}class SuperClass { static { System.out.println("SuperClass init!"); } public static int value = 123;}class SubClass extends SuperClass { static { System.out.println("SubClass init!"); }}
输出结果:
SuperClass init!
123可以看出,SubClass并没有被初始化。
1. 对于类的加载和初始化熟悉的人应该知道输出这个结果的原因:对于静态字段只有直接定义这个字段的类才会被初始化,因此通过子类来引用父类中定义的静态字段,只会触发父类的初始化而不会触发子类的初始化。
再看下这个例子:
/** * * @author Sel * * 2014.4.1 */public class NotInitialization { public static void main(String[] args) { SuperClass[] array = new SuperClass[10]; }}class SuperClass { static { System.out.println("SuperClass init!"); } }
输出结果为空,没任何输出。
可以看出,SuperClass并没有被初始化。
2.原因:通过数组的定义来引用类,不会触发类的初始化。
最后再看一个例子:
/** * * @author Sel * * 2014.4.1 */public class NotInitialization { public static void main(String[] args) { System.out.println(SuperClass.value); }}class SuperClass { static { System.out.println("SuperClass init!"); } public static final int value = 234;}
输出结果:
234
SuperClass类的常量被用到了,但是却没有被初始化。
3.原因:常量在编译阶段会存入调用类的常量池中,本质上并没有直接引用到定义常量的类,因此不会触发该类的初始化。
换句话说,就是常量value在编译阶段存入到了NotInitialization的常量池中,对value的引用实际转化为对NotInitialization自身常量池的引用,所以不会触发到SuperClass。
以上的3中引用类的方式并没有触发类的初始化,称为被动引用。