类的初始化,包括生成对象的初始化和类的静态块的实例化。html
初始化触发的时机: 类被直接引用(主动引用)的时候。java
主动引用jvm
主动引用的情形有:函数
1. 使用new关健字实例化对象code
2. 使用类的静态变量htm
3. 使用类的静态方法对象
4. 使用反射机制调用上述操做blog
5. 程序入口 (调用main方法)生命周期
初始化顺序是:it
静态块 ---> 非静态块 ---> 构造函数。
若是有超类,则初始化顺序是:
父类静态块--->子类静态块--->父类非静态块--->父类构造函数--->子类非静态块--->子类构造函数
Example:
public class ObjectInitialTest {
public static void main(String[] args) {
System.out.println("---Initialize new Class---");
Father c = new Child();
System.out.println("---Execute chlid class method---");
Child.execute();
}
}
class Child extends Father {
static {
System.out.println("Child static block");
}
{
System.out.println("Child block");
}
public Child(){
System.out.println("Child created");
}
public static void execute() {
System.out.println("Child execute");
}
}
class Father {
static {
System.out.println("Father static block");
}
{
System.out.println("Father block");
}
public Father(){
System.out.println("Father created");
}
}
执行Father c = new Child()输出为:
---Initialize new Class---
Father static block
Child static block
Father block
Father created
Child block
Child created
执行Child.execute()输出为:
---Execute chlid class method---
Father static block
Child static block
Child execute
执行 Father c = new Child();Child.execute();输出:
---Initialize new Class---
Father static block
Child static block
Father block
Father created
Child block
Child created
---Execute child class method---
Child execute
由上述结果可知,类的静态块,只初始化一次。
结论:
在类的初始化时,只会初始化类的静态块和静态赋值语句,也就是static修饰的代码块,没有static修饰的代码块在对象实例化时才执行。
被动引用
被动引用不会触发类的初始化。
被动引用的情形:
1.引用父类的静态字段,只会初始化父类,不会初始化子类。
2.引用类的常量,不会引发类的初始化。
类的卸载
在类使用完以后,知足下面的情形,会被卸载:
1. 该类在堆中的全部实例都已被回收,即在堆中不存在该类的实例对象。
2. 加载该类的classLoader已经被回收。
3. 该类对应的Class对象没有任何地方能够被引用,经过反射访问不到该Class对象。
若是类知足卸载条件,JVM就在GC的时候,对类进行卸载,即在方法区清除类的信息。
总结
Java的类对象基本上都是在jvm的堆区中建立,在建立对象以前,会触发类加载(加载、链接、初始化),当类初始化完成后,根据类信息在堆区中实例化类对象,初始化非静态变量、非静态代码以及默认构造方法,当对象使用完以后会在合适的时候被jvm垃圾收集器回收。
对象的生命周期只是类的生命周期中使用阶段的主动引用的一种状况(即实例化类对象)。而类的整个生命周期则要比对象的生命周期长的多。