Java中自由块的执行顺序
java中的自由块分为静态的自由块和非静态的自由块这两种的执行是有区别的
非静态自由块的执行时间是在执行构造函数之前。
静态自由块的执行时间是class文件加载时执行。
执行的时间不同造成的结果是
非静态自由块可以多次执行只要初始化一个对象就会执行但是静态自由块只会在类装载的时候执行一次一般用来初始化类的静态变量的值。
每次初始化一个对象都会导致一次非静态块的执行。如果涉及到继承关系则是首先执行父类的非静态块然后是父类的构造函数接着是自己的自由块最后是自己的构造函数。静态块的执行时机是在class文件装载的时候由于class文件只会装载一次因此静态块只会执行一次后面再使用这个类时不会再执行静态块中的代码。
更细致的分析class装载的过程其实静态块的执行时机是在class装载后的初始化阶段。如果采用ClassLoader的loadclass来仅仅装载类而不初始化是不会触发静态块的执行的。采用Class的fornameString是采用了默认的initialize为true的情况也就是初始化了。如果使用fornameString nameboolean initialize ClassLoader loader设置initialize为false同样不会执行静态块。
在执行class装载后的初始化阶段包括运行方法这个方法中就是类变量的初始化语句和静态自由块语句。这个方法是由java的编译器收集信息后生成的不能显示的调用。
下面通过例子来说明
father.javapackage freeblock;public class father {static{//静态块System.out.println("fathersSTATIC free block running");}{//非静态块System.out.println("fathersfree block running");}public father(){System.out.println("fathersconstructor running");}}son.javapackage freeblock;public class son extends father{static{//静态块System.out.println("sonsSTATIC free block running");}{//非静态块System.out.println("sons freeblock running");}public son() {// TODO Auto-generated constructor stubSystem.out.println("sonsconstructor running");}}client.javapackage freeblock;public class client {public static void main(String[] args) {Class f;try {System.out.println("--------beforeload father--------");fClass.forName("freeblock.father");// fClass.forName("freeblock.father",false,ClassLoader.getSystemClassLoader());System.out.println("--------afterload father---------");System.out.println("--------beforeinitial father object--------");f.newInstance();System.out.println("--------afterinitial father object--------");} catch (ClassNotFoundException e) {e.printStackTrace();} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}Class stry {System.out.println("-------beforeload son--------");sClass.forName("freeblock.son");System.out.println("--------afterload son-------");System.out.println("--------beforeinitial son object----------");s.newInstance();System.out.println("--------afterinitial son object-----------");} catch (ClassNotFoundException e) {e.printStackTrace();} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}}}
执行结果
--------before loadfather--------
fathers STATIC free blockrunning
--------after loadfather---------
--------before initial fatherobject--------
fathers free block running
fathers constructor running
--------after initial fatherobject--------
-------before load son--------
sons STATIC free block running
--------after load son-------
--------before initial sonobject----------
fathers free block running
fathers constructor running
sons free block running
sons constructor running
--------after initial son object-----------