重温一下jvm加载类的全过程:
-
加载:通过类的完全限定名查找二进制字节码文件,通过该文件创建Class实例
-
链接:验证:Class文件符合jvm规定的文件格式;准备:为类的静态变量分配内存初始化(不包含final修饰的变量其应在编译期间分配);解析:将常量池的间接引用转换为直接引用
-
初始化:静态变量和静态块,先初始化父类,再初始化当前类
-
使用
-
卸载:gc
-
创建类
-
jvm加载类:读取xx.class文件到内存,为xx类创建一个Class实例并关联(只有JVM能创建)
-
Class实例包含该class所有完整信息,类名,包名,父类,接口,方法字段等。
因此可以通过Class实例获取class信息——反射
得到class实例:
// 静态变量class
Class cls = String.class;
// 实例反射
String s = "Hello";
Class cls = s.getClass();
// 静态方法
Class cls = Class.forName("java.lang.String");
上述Class实例是一个,因为唯一
数组(例如String[])也是一种类,而且不同于String.class,它的类名是[Ljava.lang.String;
jvm为基本类型比如int,float也创建了Class实例,int.class
可通过Class实例cls创建该类的实例:
String sts = (String)cls.newInstance();
只能生成无参public的构造函数
动态加载
用到该类才加载.class到内存,可以在运行期根据条件(比如是否存在该类)来控制加载class