1. 类加载机制
- 类初始化步骤:
加载->连接->初始化- 加载:将类的
class文件读入内存,并创建一个class对象,任何类使用时都会创建一个class对象 - 连接:又分为验证、准备、解析三步
- 验证:验证内部结构是否正确,并与其它类协调一致
- 准备:为类的静态成员分配内存,并设置默认初始化值
- 解析:将类的二进制数据中的符号引用替换为直接引用
- 初始化:默认初始化与现时初始化
- 加载:将类的
- 类加载机制:全盘委托与双亲委派
- 全盘委托:类加载器加载类时也会同时加载类中引用的其它类
- 双亲委派:如果子类加载器没有加载过这个类,就会委托给父类加载器加载,如果父类加载不到,则从自己的路径下加载
- 类加载时机:创建类的实例、访问类的静态变量、调用类的静态方法、使用反射方式强制创建类的
class对象、初始化类的子类、使用java命令运行某个主类 - 类加载器:分为根类加载器、扩展类加载器、系统类加载器
- 根类加载器
Bootstrap ClassLoader:也称为引导类加载器,负责java核心类的加载,如:System、String类;位于/lib目录下的rt.jar文件中 - 扩展类加载器
Extension ClassLoader:负责JRE扩展目录中jar包的加载;位于/lib目录下的/ext目录 - 系统类加载器
System ClassLoader:负责在JVM启动时加载来自java命令的class文件以及classpath环境变量所指定的jar包和类路径,即第三方jar包或类
- 根类加载器
2. 反射机制
- 反射:通过
Class对象动态获取信息以及动态调用方法的功能 - 实现方式
Class.forName("FullClassName"):源文件阶段;典型应用:读取配置文件获取类ClassName.class:字节码阶段;典型应用:当作锁对象obj.getClass():对象阶段,即运行阶段;典型应用:判断是否为同一个字节码对象
3. Class类
Class类:java.lang.Classstatic Class<?> forName(String className):根据全类名获取Class对象Construct<T> getConstructor(Class<?> ...parameterTypes):获取制定的公共构造方法Constract<T>[] getConstructors():获取所有公共构造方法的数组Field getField(String name):获取指定的公共类成员变量Field[] getFields():获取所有公共类成员变量的数组Method getMethod(String name, Class<?> ...parameterTypes):获取指定的公共成员方法Method[] getMethod():获取所有公共成员方法的数组T newInstance():使用无参构造创建类的实例对象boolean isEnum():类声明为Enum时返回trueConstructor<T> getDeclaredConstructor(Class<?> ...parameterTypes):获取指定的构造方法,可获取私有的构造方法Constructor<T> getDeclaredConstructors():获取所有构造方法的数组Field getDeclaredField(String name):获取指定的成员变量,可获取私有成员变量Field[] getDeclaredFields():获取所有成员变量的数组Method getDeclaredMethod(String name, Class<?> ...parameterTypes):获取指定的成员方法,可以获取私有的成员方法Method[] getDeclaredMethods():获取所有成员方法的数组Method、Field、Constructor对象都可以通过setAccessible(boolean flag)方法设置可访问性Methodinvoke(Object obj, Object ...args):调用obj对象的方法
Fieldget(Object obj):获取obj对象的字段值set(Object obj, Object value):设置obj对象的字段值为value
ConstructornewInstance(Object ... initargs):创建对象
- 泛型检查只在编译期有效,运行期会被擦除,故可以通过反射越过泛型检查
4. 动态代理
-
动态代理:在程序运行中产生代理对象;基于反射机制;
Java内置的代理只能针对接口 -
JDK代理:使用java.lang.reflect.Proxy类与InvacationHandler接口实现/* 创建被代理对象 */ final Object obj = new Object(); /* 创建代理对象 */ Object proxy = Proxy.newProxyInstance(obj.getClass(), obj.getClass.getInterfaces(), new InvocationHandler() { /* 通过代理对象调用时最终会执行invoke方法 */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { /* 调用被代理对象方法前执行语句 */ System.out.println("check..."); /* 调用被代理对象的方法 */ Object invoke = method.invoke(obj, args); /* 调用被代理对象方法后执行语句 */ System.out.println("log..."); /* 返回执行结果 */ return invoke; } }); /* 通过代理对象调用指定的方法 */ proxy.equals(); -
Cglib代理:使用net.sf.cglib.proxy.Enhancer类与MethodInterceptor接口实现/* 创建被代理对象 */ final Object obj = new Object(); /* 创建Enhancer对象 */ Enhancer enhancer = new Enhancer(); /* 设置被代理的类 */ enhancer.setSuperclass(obj.getClass()); /* 设置回调方法 */ enhancer.setCallback(new MethodInterceptor() { /* 通过代理对象调用时最终会执行intercept方法 */ @Override public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { /* 调用被代理对象方法前执行语句 */ System.out.println("check..."); /* 调用被代理对象的方法 */ Object invoke = method.invoke(obj, args); /* 调用被代理对象方法后执行语句 */ System.out.println("log..."); /* 返回执行结果 */ return invoke; } }); /* 创建代理对象 */ Object proxy = (Object) enhancer.create(); /* 通过代理对象调用指定的方法 */ proxy.equals();
5. 泛型反射
-
泛型反射:从参数化数组中获取实际类型参数
ArrayList<Integer>:整体为参数化类型,Integer为实际类型参数ArrayList<E>:E为类型通用参数变量,<>表示typeof
-
public Type[] getGenericInterfaces():获取带有泛型的接口类型 -
public Type getGenericSuperclass():获取带有泛型的父类类型 -
获取父类泛型示例;该代码位于父类的构造方法中
/* 获取子类字节码对象 */ Class c = this.getClass(); /* 获取带有泛型的父类 */ ParameterizedType type = (Parameterized) c.getGenericSuperclass(); /* 获取泛型的Class对象 */ Class clazz = (Class) type.getActualTypeArguments()[0];