单纯看标题的话,可能都不知道本博文要讲的什么东西,我是一个实践主义的人,所以还是先用例子来引入吧。
大家不妨看一下下面的例子,然后想一下会输出什么。
/**
*
* @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中引用类的方式并没有触发类的初始化,称为被动引用。