运行时信息(RunTime Type Information,RTTI)使得可以在程序运行时发现和使用类型信息。
RTTI主要用来获取向上转型之后的对象到底是什么具体类型。
CLass对象
JAVA使用Class对象来执行RTTI。每个类都有一个Class对象,用来创建这个类的所有对象,
反过来说,每个类的对象都会关联同一个Class对象(数组的话,维数和类型一直的数组Class对象才相同)。
Class对象发生在类加载的时候(java.lang.ClassLoader)
Java.lang.Class类实现了Serializable、GenericDeclaration、Type、AnnotatedElement四个接口,分别实现了可序列化、泛型
定义、类型、元数据(注解)的功能。可以把Class对象理解为一个类在内存中的接口代理(代理了这个类的类型信息方法签名、属性)
Class只有一个私有的无参构造方法,也就是说CLass的对象创建只有JVM可以完成。
如何获取Class对象
所有的引用数据类型的类名、基本数据类型都可以通过.Class方式获取其Class对象,通过这种方式获取CLass对象就做类的字面常量。
Class的forname(String name)也可以获取一个Class对象
对于应用数据类的引用(必须初始化),可以通过Object类继承的getClass()方法获取这个引用的Class对象
前两种是创建Class对象,后一种是取到Class对象
JAVA反射机制
java.lang.class与java.lang.reflect.*包中的类提供了有别于RTTI的反射机制。
JAVA动态代理
JAVA自带的动态代理基于java.lang.reflect.Proxy java.lang.reflect.InvocationHandler两个类完成,使用JAVA反射机制。
创建代理对象
Object proxy = Proxy.newProxyInstance(定义代理对象的类加载器,要代理的目标对象的归属接口数组,回调接口InvacationHandler)
JDK的动态代理会创建一个$Proxy0的类,这个类继承了Proxy并且实现了要代理的目标对象的接口,但是在JDK中找不到这个类,因为它是动态
生成的。Public final class $Proxy0 extends Proxy implements目标对象的接口1,接口2..{构造方法 Public $Proxy0(InvacationHandler h)}
请求->代理对象->Proxy->InvocationHandler->目标对象
目标对象的方法调用被Proxy拦截,在InvocationHandler中回调方法中通过反射调用。这种动态代理的方法实现了对类的方法的运行时修改。
InvocationHandler这个接口,它只有一个方法invoke()需要实现,这个方法会在目标对象的方法调用的时候被激活。可以在这里控制目标对象的方法调用,
在调用前后插入一些其他操作。
为什么要用invoke()方法
主要是为了反射,这样你可以在不知道具体的类的情况下,根据配置的字符串去调用一个类的方法。
![](https://img2024.cnblogs.com/blog/35695/202408/35695-20240826070647288-243310440.jpg)