1、静态加载:编译时加载相关的类,如果没有则报错,依赖性太强
2、动态加载:运行时加载需要的类,如果运行时不用该类,则不报错,降低了依赖性
类加载的时机:
1.当创建对象时
2.当子类被加载时
3.调用类中的静态成员时
4.通过反射
连接阶段--验证:
1.目的是为了确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全
2.包括:文件格式验证、元数据验证、字节码验证和符号引用验证
3.可以考虑使用-Xverify:none参数来关闭大部分的类验证措施,缩短虚拟机类加载的时间
连接阶段--准备:
JVM会在该阶段对静态变量,分配内存空间并默认初始化(对应数据类型的默认初始值,如0、0L、null、false等)这些变量所使用的内存都将在方法区中进行分配
连接阶段--解析:
虚拟机将常量池内的符号引用替换为直接引用的过程
Initialization(初始化)
1.到初始化阶段,才真正开始执行类中定义的java程序代码,此阶段是执行<clinit>()方法的过程
2.<clinit>()方法是由编译器按语句在源文件中出现的顺序,依次自动收集类中的所有静态变量的赋值动作和静态代码块中的语句,并进行合并
3.虚拟机会保证一个类的<clinit>()方法在多线程环境中被正确地加锁、同步,如果多个线程同时去初始化一个类,那么只会有一个线程去执行这个类的<clinit>()方法,其它线程都需要阻塞等待,直到活动线程执行<clinit>()方法完毕
通过反射获取类的结构信息:
第一组:java.lang.Class类
1.getName:获取全类名
2.getSimpleName:获取简单类名
3.getFields:获取所有public修饰的属性,包含本类以及父类的
4.getDeclaredFields:获取本类中所有属性
5.getMethods:获取所有public修饰的方法,包含本类及父类的
6.getDeclaredMethods:获取本类所有方法
7.getConstructors:获取所有public修饰的构造器,包含本类以及父类
8.getDeclaredConstructors:获取本类中所有构造器
9.getPackage:以Package形式返回包信息
10.getSuperClass:以Class形式返回父类信息
11.getInterfaces:以Class[]形式返回接口信息
12.getAnnotations:以Annotation[]形式返回注解信息
public class ReflectionUtils {
public static void main(String[] args) throws Exception{
Class<?> personCls = Class.forName("reflection_.Person");
// 1.getName:获取全类名
System.out.println(personCls.getName());//reflection_.Person
// 2.getSimpleName:获取简单类名
System.out.println(personCls.getSimpleName());//Person
// 3.getFields:获取所有public修饰的属性,包含本类以及父类的
Field[] fields = personCls.getFields();
for (Field field : fields) {
System.out.println(field.getName());
}
// 4.getDeclaredFields:获取本类中所有属性
Field[] declaredFields = personCls.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println(declaredField.getName());
}
// 5.getMethods:获取所有public修饰的方法,包含本类及父类的
Method[] methods = personCls.getMethods();
for (Method method : methods) {
System.out.println(method.getName());
}
// 6.getDeclaredMethods:获取本类所有方法
Method[] declaredMethods = personCls.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println(declaredMethod.getName());
}
// 7.getConstructors:获取本类所有public修饰的构造器,不包含父类的
Constructor<?>[] constructors = personCls.getConstructors();
for (Constructor<?> constructor : constructors) {
System.out.println(constructor.getName());
}
// 8.getDeclaredConstructors:获取本类中所有构造器
Constructor<?>[] declaredConstructors = personCls.getDeclaredConstructors();
for (Constructor<?> declaredConstructor : declaredConstructors) {
System.out.println(declaredConstructor.getName());
}
// 9.getPackage:以Package形式返回包信息
System.out.println(personCls.getPackage());//reflection_
// 10.getSuperClass:以Class形式返回父类信息
Class<?> superclass = personCls.getSuperclass();
System.out.println(superclass);//class reflection_.Parent
// 11.getInterfaces:以Class[]形式返回接口信息
Class<?>[] interfaces = personCls.getInterfaces();
for (Class<?> anInterface : interfaces) {
System.out.println(anInterface);
}
// 12.getAnnotations:以Annotation[]形式返回注解信息
Annotation[] annotations = personCls.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
}
}
class Parent{
public String hobby;
public void say(){};
}
class Person extends Parent{
public String name;
protected int age;
String job;
private double salary;
//方法
public void m1(){}
protected void m2(){}
void m3(){}
private void m4(){}
}
第二组:java.lang.reflect.Field类
1.getModifiers:以int形式返回修饰符(默认修饰符是0、public是1、private是2、protected是4,static是8、final是16)含有多个修饰符则进行相加(public(1) + static(8) = 9)
2.getType:以Class形式返回类型
3.getName:返回属性名
第三组:java.lang.reflect.Method类
1.getModifiers:以int形式返回修饰符(默认修饰符是0、public是1、private是2、protected是4,static是8、final是16)含有多个修饰符则进行相加(public(1) + static(8) = 9)
2.getReturnType:以Class形式获取返回类型
3.getName:返回方法名
4.getParameterTypes:以Class[]返回参数类型数组
第四组:java.lang.reflect.Constructor类
1.getModifiers:以int形式返回修饰符
2.getName:返回构造器名(全类名)
3.getParameterTypes:以Class[]返回参数类型数组