反射
什么是反射
反射是程序在运行过程中动态加载/修改/访问任意类的能力
要实现反射,Class类的存在是很关键的一个点
每一个被加载进程序的类都会被转换成字节码并以一个Class对象的形式储存在内存中
假如你要加载一个Person类,那么这个Person类被加载完毕后会变成一个Class对象,这个Class对象以字节码的形式储存所有关于Person类的信息
有了一个类的所有信息,就可以访问他的Constructor, Fields, Methods, Annotations..
我们甚至可以访问私有,通过在访问之前setAccessable to true.
获取类的方式
- 通过内部类获取
- 通过对象获取
- 通过外部类获取
前两种都比较简单,因为类在你程序运行之前就已经被加载了,也就是说,前两种方法的类,必须在你写代码的时候就存在,并且你可以调用它,不然编译器会报错
// 通过类获取
String.class;
// 通过对象获取
String name = "";
name.getClass();
第三种方法即使在目前这个类不存在的情况下编译器也不会报错,只不过如果这个程序运行的时候,这个类还不存在,那么程序就会出错,这就实现了动态加载
Class.forName();
想象一下,写框架的时候,你的框架是为别人的类服务的,所以你要获取的类很可能不在本地,甚至在你写框架的时候,这个类根本就没有,这个时候,就要用到这里的第三种方法来动态加载这个类,只需要别人在使用你的框架的时候,这个类存在就行了
注解
如果说comments是给人读的注释,那么annotations就是给机器读的注释
注解有很多用途,可以用来压制警告,显式废弃掉一个方法
但以我现在的知识水平,我认为注解最有实际意义的地方是配合反射的使用
内置注解
内置注解看API就好了,这里主要讲自定义注解
自定义注解与反射的配合使用
反射可以获取一个类的信息,包括这个类的注解,前提是这个注解的Retention 被设置为 Runtime,这样才能在运行时获取,Class或Resource都会导致注解无法被加载到JVM中,运行时无法被获取
有了反射,就可以直接访问注解的内容,由于每个注解都和一个Field/Type绑定,所以可以用注解做很多事情,例如给予一个Field一个别名,或者描述这个Field的别的信息,以供使用它们的框架去分析和使用
例如数据库,我们有一个field: String columnName="Name".
但是数据库中一个Column的创建不能只有名称,他还得有数据类型,AI,PK,这些变量,就可以通过在field上方加annotation来给框架充分的信息去创建数据库
个人认为,反射和自定义注解主要在写框架的时候才会频繁使用,其它场景使用机会不大