以下代码的输出结果是?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public class StaticTest { public static StaticTest t1 = new StaticTest(); public static StaticTest t2 = new StaticTest(); static { System.out.println("静态块" ); } { System.out.println("构造块" ); } public static void main (String[] args) { StaticTest t = new StaticTest(); } }
A. 静态块 构造块 构造块 构造块
B. 构造块 静态块 构造块 构造块
C. 构造块 构造块 静态块 构造块
D. 构造块 构造块 构造块 静态块
1 2 3 4 5 6 7 $ /Library/Java/JavaVirtualMachines/jdk-13.0.2.jdk/Contents/Home/bin/java -javaagent:/Applications/IntelliJ IDEA.app/Contents/lib/idea_rt.jar=51677:/Applications/IntelliJ IDEA.app/Contents/bin -Dfile.encoding=UTF-8 -classpath /Users/onns/Documents/code/java/jvm/out/production/jvm xyz.onns.nowcoder.StaticTest 构造块 构造块 静态块 构造块 Process finished with exit code 0
开始时 JVM 加载 StaticTest.class,对所有的静态成员进行声明,t1、t2 被初始化为默认值null
。
又因为 t1、t2 需要被显式初始化,所以对 t1 进行显式初始化,初始化代码块 → 构造函数(没有就是调用默认的构造函数)。
因为在开始时已经对 static 部分进行了初始化,虽然只对 static 变量进行了初始化,但在初始化 t1 时也不会再执行 static 块了,因为 JVM 认为这是第二次加载类 B 了,
所以 static 会在 t1 初始化时被忽略掉,所以直接初始化非 static 部分,也就是构造块部分(输出’构造块’)接着构造函数(无输出)。
接着对 t2 进行初始化过程同 t1 相同(输出’构造块’)。
此时就对所有的 static 变量都完成了初始化,接着就执行 static 块部分(输出’静态块’)。
接着执行,main 方法,同样也,new 了对象,调用构造函数输出(‘构造块’)。
进阶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 public class B { public static B t1 = new B(); public static B t2 = new B(); public B () { super (); System.out.println("B类构造块" ); } static { System.out.println("B类静态块" ); } } public class A extends B { public static A t1 = new A(); public static A t2 = new A(); public A () { super (); System.out.println("A类构造块" ); } static { System.out.println("A类静态块" ); } public static void main (String[] args) { A t = new A(); } }
参考链接