根据上一节的理论我们知道,每个类的接口被Java程序“首次主动使用”时才初始化,这一节我们就通过具体的实例来验证一下
- 创建类的实例
public class MyTest1 {
public static void main(String[] args) {
new MyParent1();
}
}
class MyParent1 {
public static String str = "hello world";
static {
System.out.println("MyParent static block");
}
}
运行程序,输出:
MyParent static block
类的静态代码块被执行了,说明类进行了初始化
- 访问某个类或接口的静态变量,或者对该静态变量赋值
public class MyTest1 {
public static void main(String[] args) {
System.out.println(MyParent1.str);
}
}
class MyParent1 {
public static String str = "hello world";
static {
System.out.println("MyParent static block");
}
}
运行程序,输出:
MyParent static block
hello world
- 调用类的静态方法
public class MyTest1 {
public static void main(String[] args) {
MyParent1.print();
}
}
class MyParent1 {
public static String str = "hello world";
public static void print(){
System.out.println(str);
}
static {
System.out.println("MyParent static block");
}
}
运行程序,输出:
MyParent static block
hello world
- 反射
public class MyTest1 {
public static void main(String[] args) throws ClassNotFoundException {
Class.forName("com.shengsiyuan.jvm.classloader.MyParent1");
}
}
class MyParent1 {
public static String str = "hello world";
static {
System.out.println("MyParent static block");
}
}
运行程序,输出:
MyParent static block
- 初始化一个类的子类
public class MyTest1 {
public static void main(String[] args) throws ClassNotFoundException {
new MyChild1();
}
}
class MyParent1 {
public static String str = "hello world";
static {
System.out.println("MyParent static block");
}
}
class MyChild1 extends MyParent1 {
public static String str2 = "welcome";
static {
System.out.println("MyChild1 static block");
}
}
运行程序,输出:
MyParent static block
MyChild1 static block
- Java虚拟机启动时被表明为启动类的类
public class MyTest1 {
static {
System.out.println("MyTest1 static block");
}
public static void main(String[] args) throws ClassNotFoundException {
}
}
运行程序,输出:
MyTest1 static block
非主动使用注意点
以上实例都是对主动使用的验证,我们来看一下下面这个程序
public class MyTest1 {
public static void main(String[] args) throws ClassNotFoundException {
System.out.println(MyChild1.str);
}
}
class MyParent1 {
public static String str = "hello world";
static {
System.out.println("MyParent static block");
}
}
class MyChild1 extends MyParent1 {
static {
System.out.println("MyChild1 static block");
}
}
运行程序,输出:
MyParent static block
hello world
我们可以看到,MyChild1 static block
并没有打印出来,这里我们调用MyChild1.str明明是对类的静态变量的访问,但是MyChild1却没有被初始化,所以这里要注意的一点就是:
对于静态字段来说,只有直接定义了该字段的类才会被初始化
参考资料:
圣思园JVM课程