类的生命周期为加载、连接、初始化、使用和卸载。当Java程序需要某个类型的时候,需要确保这个类型已经完成了加载、连接和初始化。每个Jvm实现必须在类型首次主动使用时完成初始化。
首次:表明类型只会加载一次
主动使用:主动使用分为以下七种情况:
构建某个类的实例
访问类的静态变量或者修改类的静态变量
调用类的静态方法
反射(Class.forName())
初始化子类
JVM启动时被标为启动类(包含Main方法的类)
JDK1.7之后的动态语言支持
综上,只有以上七种情况才会导致类的初始化,其他的被动使用情况不会导致类的初始化,但是可能会导致加载和连接。
类的加载
类的加载是将.class文件读入内存中,将其放在运行时数据区的方法区内,然后在内存中创建一个java.lang.Class对象(存放在方法区),该对像用来封装类在方法区的数据结构,是.class文件的映射。
加载class文件的方式
本地系统加载
网络下载的文件
从zip、jar等归档文件中加载
从数据库中加载
从Java源文件动态编译出.class文件,如动态代理
类的初始化
在此阶段,会为静态变量赋指定值,运行静态代码块。
实例
public class Main {
public static void main(String[] args) {
//第一处
System.out.println(Son.a);
}
}
class Parent{
public static int a=3;
static {
System.out.println("I am parent");
}
}
class Son extends Parent{
static {
System.out.println("I am son");
}
}
//第一处的解析
// 虽然调用了Son.a,但是对于Son来说,并不是主动使用,因此没有完成Son初始化
// a是Parent的静态变量,实际是Parent的类信息,因此也就是Parent的主动使用。
// 方法区中开辟了一块Parent的内存,用于存放其Class信息,Son只是可以访问到这块内存,而并不是这块内存的主人
该案例的运行结果为
I am parent
3
注意点:此时并未运行Son的静态代码块,因为Son并未完成初始化。
网友评论