java类初始化中类成员的执行顺序解析
2016-10-27 21:16
218 查看
java类初始化中类成员的执行顺序解析
java初始化过程中,代码块,static代码块,实例成员变量,static变量,static方法和普通方法初始化顺序是怎样的呢?首先看一段代码块,分析其输出打印结果
public class App { private static App d = new App(); private SubClass t = new SubClass(); static { System.out.println(3); } { System.out.println(5); } { System.out.println(6); } public App() { System.out.println(4); } public static void main(String[] args) { System.out.println("hello"); } } class SuperClass//父类 { SuperClass() { System.out.println("构造器SuperClass"); } static { System.out.println("superclass静态初始化"); } } class SubClass extends SuperClass //子类 { static { System.out.println(1); } { System.out.println(7); } public SubClass() { //super(); System.out.println(2); } }
打印出的答案为:
为什么是这样的结果呢 ??
首先java中共有三种代码块:局部代码块,初始化代码块,静态初始化代码块
1.此题局部代码块不在我们考虑范围
2.初始化代码块(构造代码块):直接定义在类中
每次创建对象的时候都会先执行初始化代码块,通过反编译看到其本质是放到构造器中super()构造器后执行,优先于本类构造器代码先执行,完成初始化.
3.静态初始化代码块:使用static修饰的普通初始化代码块
所在类被加载时按顺序加载到的时候才执行初始化,优先于main方法执行
并且我们先记住3点
1.static修饰的变量和方法是随class的加载而加载并完成初始化的
2.static修饰的变量和方法是按照顺序加载的
3.实例变量是通过new调用构造器创建实例的时候才开始执行初始化的
好接下来我们来分析初始化过程:
1.首先第一步先加载第一个static语句,d声明后储存在方法区中,并调用构造器创建App实例
2.此时构造器会加载非静态变量
①.发现SubClass类型变量,先去包中寻找相关的类,找到SubClass后,再去找其父类SuperClass
②.找到SubClass所有关联类之后,先加载父类字节码文件,此时SuperClass(static代码块完成初始化,打印”superclass静态初始化”),然后再加载SubClass(加载时完成初始化,打印出”1”);
3.加载完关联类之后,调用SubClass构造器,SubClass构造器会默认先调用super()父类构造器输出(“构造器SuperClass”父类构造器总是在子类构造器第一行调用),
然后开始执行子类初始化代码段,其本质是在构造器中初始化,在父类构造器后执行,优先于子类构造器内容执行,输出代码“7”,然后执行子类构造器中代码输出”2”.
4.然后按顺序执行App构造器中初始化代码块,输出“5”“6”,然后执行构造器App()中代码,输出4;
5.实例变量加载完之后,按顺序加载static变量,此时开始加载static代码块,输出3.
6.在加载字节码文件最后执行main方法,输出”hello”
分析完成
最后,按照以上思路,大家分析一下下面代码的打印结果:
public class App { private static App d = null;//stataic字段的初始化, {System.out.println("代码块啊");} private SubClass t = new SubClass();//非static字段的初始化其实都在构造器中,优先执行的. static { d = new App(); System.out.println(3); } public App() { //t = new SubClass(); //----------------------------------- System.out.println(4); } public static void main(String[] args) { System.out.println("Hello"); } } //父类 class SuperClass { SuperClass() { System.out.println("构造SuperClass"); } } //子类 class SubClass extends SuperClass { static { System.out.println(1); } SubClass() { //super();//表示调用父类无参数构造器 System.out.println(2); } }
运行结果为下图:
大家分析一下能否得到这个结果。
相关文章推荐
- Java类成员变量、普通成员变量、初始化块、构造方法的初始化和执行顺序
- Java中创建对象时,初始化成员变量的代码的执行顺序
- java程序在执行过程中,类,对象以及它们成员加载、初始化的顺序如下:
- Java初始化顺序总结及其程序执行过程图- 静态变量、静态代码块、成员变量、构造函数
- Java成员变量初始化和执行顺序
- java类的成员初始化顺序
- java成员变量的初始化顺序
- java静态代码块、初始化块和构造方法的执行顺序解析
- java 静态初始化,动态初始化,以及构造器执行的顺序
- java静态/动态成员变量、初始化块,父类/子类构造函数执行顺序问题
- Java中类成员初始化顺序问题
- Java牛角尖【003】:类初始化时的执行顺序
- 一个关于继承关系中静态快、成员变量、构造体代码的执行顺序的Java代码
- java笔记一:类成员的初始化顺序
- 理解Java类中构造方法的执行顺序和变量初始化
- Java中的成员初始化顺序和内存分配过程
- Java中的static变量、方法、代码块初始化执行顺序
- 类成员初始化与构造函数执行的顺序 转自:http://www.cnblogs.com/anderslly/archive/2008/07/12/why-do-initializers-run-in-the-opposite-order-as-constructors.html
- java变量,初始化快,构造函数的执行顺序
- 【java】静态&初始化执行顺序