类的加载连接于初始化
其他
2018-10-23 16:11:20
阅读次数: 0
类的加载
- 通过jvm提供的系统类加载器加载类的二进制数据
- 类的来源: 本地class文件,jar包,网络加载,把java文件动态编译,并加载。
连接
- 加载以后生成class对象,将二进制数据合并到 jre(jdk)中
- 验证: 验证类的内部结构
- 准备:为类变量分配内存,并设置默认值
- 解析: 将符号(变量)引用替换为直接引用(二进制数据)。
类的初始化
- 主要目的是对类变量进行初始化(显式)
- 先加载和连接,再初始化
- 若父类还没有初始化,则先初始父类
- jvm总是最先初始化Object
类初始化的时机
- 创建类的实例,new ,反射,反序列化
- 调用类方法,类成员,赋值
- class.forName()
- 初始化这个类的子类
- 直接运行该类
- 用final修饰的变量,若在编译时已经确定其值,则编译器会把所有使用该变量的地方直接换成值,因而使用这个变量不会初始化类
- 当时用classLoder的loadClass(),加载类时,只是加载该类,不进行初始化,class.forName静态方法会强制初始化。
类加载器
- (bootstrap)根类加载器->(extension)扩展类加载器->(system)系统类加载器->用户类加载器
- 根类加载器加载java核心类
- 系统类加载器的加载路径是当前路径
- 自定义加载器可以通过继承ClassLoader实现。
- URLClassLoader类 通过构造器初始化。
java8方法参数反射
反射与泛型
- field.getType() : 获取变量类型
- field.getGenericType(): 获取field的泛型类型
-
// public Map<String,String> a;
Class<MyTest> myTestClass = MyTest.class;
Field a = myTestClass.getDeclaredField("a");
Class<?> type = a.getType();
System.out.println(type);
//获取原始类型 interface java.util.Map
Type genericType = a.getGenericType();
System.out.println(genericType);
//获取泛型类型 java.util.Map<java.lang.String, java.lang.String>
ParameterizedType genericType1 = (ParameterizedType) genericType;
System.out.println(genericType1+"-------");
//泛型类型参数化: java.util.Map<java.lang.String, java.lang.String>-------
genericType1.getRawType();
//获取原始类型:interface java.util.Map
System.out.println(genericType1.getRawType());
System.out.println(genericType1.getActualTypeArguments());
//获取泛型参数:[Ljava.lang.reflect.Type;@69663380
for (Type t: genericType1.getActualTypeArguments()) {
System.out.println(t);
//class java.lang.String
}
System.out.println(genericType1.getOwnerType());
//null
转载自blog.csdn.net/qq_38003454/article/details/83214718