有关于RTTI和反射的总结
目的
在读JAVA编程思想对于RTTI的叙述中,对其一部分总结内容如下, RTII是指的Run-Time Type Identification。从意思来说就知道这个机制的目的就是为了实现运行时识别对象和类的信息,而JAVA 这门语言就采用了两种方式来实现这个目的。
-
一则传统的RTTI,我们常见的这个机制的形式有三种(1、类型转换<由RTTI保证类型转换的正确性> 2、查询class对象获取运行时所需要的信息。3、关键字instanceof)。这种形式其实是运行期已经知道了所有引用的具体类型。
-
另一种就是反射机制。
这两种机制主要的区别就是我们需要识别的那个对象(类)在编译期是已知的还是未知的。
这两种机制都离不开一个重要的对象,Class对象。
Class对象
这个对象的常用于的功能一般是获得有关类的详细信息
Class对象是JAVA用以执行RTTI的。某个类的Class对象被加载到内存中是用于用来创建具体的对象。获取到恰当的Class对象的引用有几种方式可以获取
-
通过forName() 。这种方式会引发初始化。也就是说在这个方法运行的时候这个s指向的类也就初始化了(执行了静态代码块)
Class c = Class.forName(s)
s是一个类的全限定名的字符串。 -
通过类字面型常量。
Class c = Student.Class
这种方式不会引发初始化。初始化的过程会在你调用方法或者非常数静态域首次引用时执行。 -
通过getClass() 。这个是定义在Object中的方法。所以必须是特定的对象调用这个方法才能产生Class对象。
当然在JAVA SE5 之后,与泛型的语法结合在一起之后,我们可以将它的类型规定的更加具体。以便于在编译器中就可以发现自己由于疏忽在coding时犯下的错误。
反射
RTTI机制的限制就是编译器必须要知道所有通过这个机制处理的类。而反射并不需要在编译期有.class文件的存在(运行时通过网络获取)。反射其实也就是通过Class对象中封装的方法从而在运行的时候获取类的详细信息。
代理
代理得作用主要是有效得将具体得实现方和调用类解耦,还可以借用代理增加一部分得功能而不需要修改具体实现类得代码。代理具体应有四个角色组成
- 客户端。这个是具体要去调用得那一方
- 抽象主题。这个一般表示为接口。这是代理类和实现类可以开放供访问得共同部分。
- 被代理角色。就是指具体得实现类。
- 代理类。
静态代理
静态代理代理类一般是运行之前就存在编译好了的类。它的实现如下图所示。《此处代码来源:B站UP主子烁爱学习 》
但是如果我们有多个类需要代理时,静态代理的写法会产生很多代理类,因此JDK为我们提供了创建动态代理的方式,
JDK动态代理
实现如下图所示
通过掉用 Proxy.newProxyInstance
返回了一个实现了特定接口的动态代理。所以我们通过这种写法最终会将请求转发到被代理类上。但是这种写法只能对实现了特定接口的类的动态代理。如果有一个类并未实现Speaker这个接口,我们就需要别的方式
CGLib_动态代理
这是第三方JAR包提供的对于上述方式缺点的补充。(菜鸟起步阶段,后续再看)