关于静态块、静态属性、构造块、构造方法的执行顺序
2014-05-15 14:42
316 查看
下面是在网上找到的比较典型的例子,以此来说明
例一:
该段代码的执行结果为:
A的静态块
A的静态属性初始化
B的静态属性初始化
B的静态块
A的实例属性初始化
A的实例块
A的构造方法
B的实例块
B的实例属性初始化
B的构造方法
A的实例属性初始化
A的实例块
A的构造方法
B的实例块
B的实例属性初始化
B的构造方法
由此可见,实例化子类的时候,若此类未被加载过,首先加载是父类的类对象,然后加载子类的类对象,接着实例化父类,最后实例化子类,若此类被加载过,不再加载父类和子类的类对象。
接下来是加载顺序,当加载类对象时,首先初始化静态属性,然后执行静态块;当实例化对象时,首先执行构造块(直接写在类中的代码块),然后执行构造方法。至于各静态块和静态属性初始化哪个些执行,是按代码的先后顺序。属性、构造块(也就是上面的实例块)、构造方法之间的执行顺序(但构造块一定会在构造方法前执行),也是按代码的先后顺序。
例二:
该段代码的执行结果为:
父类--非静态代码块
父类--构造函数
父类--静态代码块
父类--非静态代码块
父类--构造函数
子类--非静态代码块
子类--构造函数
子类--静态代码块
父类--非静态代码块
父类--构造函数
子类--非静态代码块
子类--构造函数
父类--非静态代码块
父类--构造函数
子类--非静态代码块
子类--构造函数
分析(非静态代码块即构造块):
首先要加载父类EXA,由于A的静态属性在静态块的前面,先初始化静态属性(new EXA())(父类--非静态代码块;父类--构造函数),然后是静态块(父类--静态代码块);
加载子类EXC,由于EXC的静态属性也在静态块的前面,先初始化静态属性(new EXC()),实例化子类对象的时候会先实例化父类,所以执行的顺序为(父类--非静态代码块;父类--构造函数;子类--非静态代码块;子类--构造函数),然后是静态块(子类--静态代码块)
实例化父类EXA对象:父类--非静态代码块;父类--构造函数;
实例化子类EXC对象:子类--非静态代码块;子类--构造函数;
第二个new EXC():因为父类和子类都已加载,只需依次实例化父类对象和子类对象(父类--非静态代码块;父类--构造函数;子类--非静态代码块;子类--构造函数;)
推测:若将EXA的静态块和静态属性的初始化换位置,执行结果应该为:
父类--静态代码块
父类--非静态代码块
父类--构造函数
父类--非静态代码块
父类--构造函数
子类--非静态代码块
子类--构造函数
子类--静态代码块
父类--非静态代码块
父类--构造函数
子类--非静态代码块
子类--构造函数
父类--非静态代码块
父类--构造函数
子类--非静态代码块
子类--构造函数
运行发现,结果证实这样。
例一:
class A { static { System.out.println("A的静态块"); } private static String staticStr = getStaticStr(); private String str = getStr(); { System.out.println("A的实例块"); } public A() { System.out.println("A的构造方法"); } private static String getStaticStr() { System.out.println("A的静态属性初始化"); return null; } private String getStr() { System.out.println("A的实例属性初始化"); return null; } public static void main(String[] args) { new B(); new B(); } } class B extends A{ private static String staticStr = getStaticStr(); static { System.out.println("B的静态块"); } { System.out.println("B的实例块"); } public B() { System.out.println("B的构造方法"); } private String str = getStr(); private static String getStaticStr() { System.out.println("B的静态属性初始化"); return null; } private String getStr() { System.out.println("B的实例属性初始化"); return null; } }
该段代码的执行结果为:
A的静态块
A的静态属性初始化
B的静态属性初始化
B的静态块
A的实例属性初始化
A的实例块
A的构造方法
B的实例块
B的实例属性初始化
B的构造方法
A的实例属性初始化
A的实例块
A的构造方法
B的实例块
B的实例属性初始化
B的构造方法
由此可见,实例化子类的时候,若此类未被加载过,首先加载是父类的类对象,然后加载子类的类对象,接着实例化父类,最后实例化子类,若此类被加载过,不再加载父类和子类的类对象。
接下来是加载顺序,当加载类对象时,首先初始化静态属性,然后执行静态块;当实例化对象时,首先执行构造块(直接写在类中的代码块),然后执行构造方法。至于各静态块和静态属性初始化哪个些执行,是按代码的先后顺序。属性、构造块(也就是上面的实例块)、构造方法之间的执行顺序(但构造块一定会在构造方法前执行),也是按代码的先后顺序。
例二:
public class EXA { private static EXA a = new EXA(); static { System.out.println("父类--静态代码块"); } public EXA() { System.out.println("父类--构造函数"); } { System.out.println("父类--非静态代码块"); } public static void main(String[] args) { new EXC(); new EXC(); } } class EXC extends EXA { private static EXC b = new EXC(); static { System.out.println("子类--静态代码块"); } { System.out.println("子类--非静态代码块"); } public EXC() { System.out.println("子类--构造函数"); } }
该段代码的执行结果为:
父类--非静态代码块
父类--构造函数
父类--静态代码块
父类--非静态代码块
父类--构造函数
子类--非静态代码块
子类--构造函数
子类--静态代码块
父类--非静态代码块
父类--构造函数
子类--非静态代码块
子类--构造函数
父类--非静态代码块
父类--构造函数
子类--非静态代码块
子类--构造函数
分析(非静态代码块即构造块):
首先要加载父类EXA,由于A的静态属性在静态块的前面,先初始化静态属性(new EXA())(父类--非静态代码块;父类--构造函数),然后是静态块(父类--静态代码块);
加载子类EXC,由于EXC的静态属性也在静态块的前面,先初始化静态属性(new EXC()),实例化子类对象的时候会先实例化父类,所以执行的顺序为(父类--非静态代码块;父类--构造函数;子类--非静态代码块;子类--构造函数),然后是静态块(子类--静态代码块)
实例化父类EXA对象:父类--非静态代码块;父类--构造函数;
实例化子类EXC对象:子类--非静态代码块;子类--构造函数;
第二个new EXC():因为父类和子类都已加载,只需依次实例化父类对象和子类对象(父类--非静态代码块;父类--构造函数;子类--非静态代码块;子类--构造函数;)
推测:若将EXA的静态块和静态属性的初始化换位置,执行结果应该为:
父类--静态代码块
父类--非静态代码块
父类--构造函数
父类--非静态代码块
父类--构造函数
子类--非静态代码块
子类--构造函数
子类--静态代码块
父类--非静态代码块
父类--构造函数
子类--非静态代码块
子类--构造函数
父类--非静态代码块
父类--构造函数
子类--非静态代码块
子类--构造函数
public class EXA { static { System.out.println("父类--静态代码块"); } private static EXA a = new EXA(); public EXA() { System.out.println("父类--构造函数"); } { System.out.println("父类--非静态代码块"); } public static void main(String[] args) { new EXC(); new EXC(); } } class EXC extends EXA { private static EXC b = new EXC(); static { System.out.println("子类--静态代码块"); } { System.out.println("子类--非静态代码块"); } public EXC() { System.out.println("子类--构造函数"); } }
运行发现,结果证实这样。
相关文章推荐
- java静态代码块/静态属性、构造块、构造方法执行、main方法、普通代码块的顺序
- 关于java中子类,父类中,静态代码块: staic{},动态代码块:{},构造方法,类属性,对象属性等执行顺序做个总结:
- 关于类中静态块,静态方法,构造代码块,构造方法的执行顺序
- java静态代码块/静态属性、构造块、构造方法执行、main方法、普通代码块的顺序
- 关于静态块,静态方法,非静态方法,构造方法执行的顺序
- 关于java代码中静态代码块、非静态构造代码块以及构造方法的执行顺序
- 关于类中静态,非静态,构造方法的执行顺序
- 关于类中静态,非静态,构造方法的执行顺序
- 当子类继承父类时,构造块,静态块,静态方法的执行顺序
- 阿里面试题:关于类中静态,非静态,构造方法的执行顺序
- java 静态属性 静态代码块 静态方法声明 构造块 构造函数 动态属性 执行顺序
- 静态块,非静态块,静态属性,非静态属性,构造的执行顺序
- 关于构造代码块 静态构造代码块 构造方法的执行顺序
- java静态代码块、构造方法、构造块的执行顺序
- java中静态块,静态方法,非静态方法,构造方法执行的顺序
- 总结java中静态块,静态方法,非静态方法,构造方法执行的顺序
- 静态代码块、代码块、构造方法、普通方法、static方法、 *静态属性、普通属性的加载顺序、执行顺序
- Java static属性和静态代码块和构造方法等的执行顺序探讨
- Java中静态块,静态成员变量,构造块,普通成员变量,构造方法的执行顺序
- 阿里面试题:关于类中静态,非静态,构造方法的执行顺序