代码运行实例
1、return与finally的执行顺序
public class Main { public static void main(String[] args) { System.out.print(fun1()); } public static String fun1() { try { System.out.print("A"); return fun2(); } finally { System.out.print("B"); } } public static String fun2() { System.out.print("C"); return "D"; } } //输出结果为ACBD,finally语句一定会执行,若有return在finally前则先执行finally
2、针对类的继承,虚拟机会如何进行父类和子类的初始化加载呢?
public class Test { public static void main(String[] args) { System.out.print(B.c); } } class A { public static String c = "C"; static { System.out.print("A"); } } class B extends A{ static { System.out.print("B"); } } //输出结果为:AC,子类引用父类静态字段,只会引发父类初始化
3、静态常量的访问
public class Test { public static void main(String[] args) { System.out.print(B.c); } } class A { static { System.out.print("A"); } } class B extends A{ static { System.out.print("B"); } public final static String c = "C"; } //输出结果为:C,常量在编译阶段会存入调用类的常量池中,本质上并没有直接引用到定义常量的类,因此不会触发定义常量的类的初始化。
4、静态常量利用new来创建
public class Test { public static void main(String[] args) { System.out.println(Test2.a); } } class Test2{ static { System.out.print("OK"); } public static final String a=new String("JD"); } //输出结果为:OKJD,跟(3)的区别在于,使用了new,则需要初始化类
注意:使用 new 关键字实例化对象的时候;读取或设置一个类的静态字段(被 final 修饰、已在编译期把结果放入常量池的静态字段除外)的时候;以及调用一个类的静态方法的时候一定会初始化类
5、final 修饰的静态变量的调用不会初始化类
public class Test { public static void main(String[] args) { System.out.println(Test2.a); } } class Test2{ public static final String a="JD"; static { System.out.print("OK"); } } //输出结果:JD,a并不是通过new还是创建的,而且a又被final修饰,故不会初始化。
6、静态代码块,非静态代码块,构造方法的执行顺序
public class Main { public static void main(String[] args) { System.out.println("A"); new Main(); new Main(); } public Main() { System.out.println("B"); } { System.out.println("C"); } static { System.out.println("D"); } } //输出结果:DACBCB,调用main方法会对类Main进行初始化,故静态方法执行,然后main方法,对类每进行一次实例化,都会在构造方法前执行非静态代码块