一、定义一个父类:
public class SuperClass {
static {
System.out.println("SuperClass init");
}
public static int value = 123;
}
定义一个子类继承自父类:
public class SubClass extends SuperClass{
static {
System.out.println("SubClass init");
}
}
测试类如下;
public class InitializationTest {
public static void main(String[] args) {
System.out.println(SubClass.value);
}
}
运行结果;
SuperClass init
123
可见对于静态变量,只有直接定义这个变量的类才会被初始化。因此把main()方法里的SubClass.value换成SuperClass.value,运行结果是一样的。
二、把上面测试类的main()方法改成这样:
public static void main(String[] args) {
// System.out.println(SubClass.value);
SuperClass sup = new SuperClass();
SuperClass sub = new SubClass();
}
运行结果:
SuperClass init
SubClass init
如果是改成这样:
public static void main(String[] args) {
// System.out.println(SubClass.value);
SuperClass[] sups = new SuperClass[5];
SuperClass[] subs = new SubClass[5];
}
运行则不会产生任何输出,这表示通过数组定义来引用某类,不会触发此类的初始化。
实际上在这种情况下,虚拟机会自动生成一个直接继承于java.lang.Object的类,这个类代表了一个一维数组,数组应有的属性和方法都实现在这个类里。而上面的代码运行的时候,这个类会得到初始化。
三、在父类中添加一个静态常量做测试:
public class SuperClass {
static {
System.out.println("SuperClass init");
}
public static int value = 123;
public static final int F_VALUE= 1234;//add
}
测试类;
public class InitializationTest {
public static void main(String[] args) {
System.out.println(SuperClass.F_VALUE);
}
}
运行结果:
1234
并没有输入“SuperClass init”,可见SuperClass没有初始化。
常量在编译阶段会存入调用类(InitializationTest 类)的常量池中,本质上并没有直接引用到定义常量的类,因此不会触发定义常量的类的初始化。
调用类(InitializationTest 类)对常量SuperClass.F_VALUE的引用实际都被转化为InitializationTest 类对自身常量池的引用了。
四、父类里加上如下构造方法;
SuperClass(){
System.out.println("SuperClass constructor");
};
测试类的main()方法如下:
public static void main(String[] args) {
System.out.println(SuperClass.value);
}
运行结果:
SuperClass init
123
可见SuperClass的构造方法并没有得到调用。
而如果把main()方法改成这样;
public static void main(String[] args) {
// System.out.println(SuperClass.value);
System.out.println(new SuperClass().value);
}
运行结果:
SuperClass init
SuperClass constructor
123
构造方法就被调用了。说明构造方法只在创建对象的时候才会被调用,类的初始化不会触发调用。而且构造方法是在类初始化之后才调用的。