Java程序初始化的顺序是怎样的?
一、类的生命周期
1. 装载:.class文件加载至方法区(永久代)的过程
2. 链接:链接分为校验、准备、解析三个过程。校验主要来确认.class文件是否适合当前的JVM(Version),以及.class文件的格式等是否正确;准备主要是为静态变量分配内存并赋默认值;解析主要是为将符号引用转换为直接引用的过程,如将常量池的代码引用转换为直接引用。
3. 初始化:通过静态代码块或非静态代码块对类进行的一些初始化操作
4. 对象实例化:初始化完成之后,将调用类的构造函数为类在堆中开辟内存空间,构造函数可以对类的变量(包括静态变量)进行一些赋值操作等
5. 对象使用:类完成实例化之后,就可以通过对象调用类中定义的方法做一些业务上的处理
6. 垃圾回收:对象使用完毕,在JVM中不存在引用链时,垃圾回收子系统就会对其进行回收,回收之前调用类的finallize方法,做销毁前的一些处理
7. 对象终结:对象实例被销毁
8. 卸载:应用进程停止,JVM会重新对堆栈方法区进行调整,类文件可能被卸载
【说明】其中,步骤4-7又可以看做是对象的生命周期
二、一个类的情况
静态变量-》静态代码块-》非静态变量-》非静态代码块-》构造函数
【说明】
1. 变量最好都在代码块或方法体之前进行声明(或赋值)
2. 静态代码块中若要使用静态变量,则静态变量要在静态代码块之前声明,否则会产生“非法前向引用”,但是却能对静态变量进行直接赋值
3. 静态代码块在类加载时只执行一次
4. 非静态代码块能对非final静态变量重新赋值
三、有继承的情况
父类的静态变量-->父类的静态代码块-->子类静态变量-->子类的静态代码块-->父类非静态变量-->父类的非静态代码块-->父类的构造器-->子类非静态变量-->子类非静态代码块-->子类构造器
【说明】
1. 继承的前提是父类要先实例化,只有有了父类才能存在子类
【思考】
1. 为什么要这样处理呢?先有父类容易理解,为什么不对父类完全实例化之后再处理子类呢,不懂
参考:
- Java程序初始化的顺序(一)
- Java程序初始化的顺序(二)
- jvm的生命周期和java类的生命周期