java反射相关类
class类
正在运行在内存中的所有类都是该类的实例对象,每个class类都包含本类的所有信息
类内部的主要信息
- Field;所有属性
- Method:所有方法
- Constructor:所有构造方法
Field类
通过反射的class类可以得到一个Field对象时,其中包含了某一个类其中一个属性的所有信息
类内部主要信息
- 标注在属性上的注解
- 属性名
- 属性的数据类型
- 属性的访问修饰符
Constructor类
描述Class类中的构造方法的一个类
类内部的主要信息
-
构造方法的访问修饰符
-
构造方法的参数
- 参数的数据类型
- 参数名字
- 标注在参数上的注解
method类
描述clsass类中所有方法(不包括构造方法的类),包括抽象方法
类内部的主要信息
- Constructor类内部主要信息相同
- 方法的返回类型
Class类内部主要信息
Field类(变量)
-
包括public和非public修饰的变量,请可以获取继承下来的变量
-
获取不了父类被protect修饰的变量
-
Field类常用方法
- Field[] getFields():获取类中所有被public修饰的所有变量
- Field getField(String name):根据变量名获取类中的一个变量,该变量必须被public修饰
- Field getDeclaredField(String name):根据姓名获取类中的某个变量,无法获取继承下来的变量
- Field[] getDeclaredFields():获取类中所有的变量,但无法获取继承下来的变量
Constructor类(构造器)
-
包括公有的和私有的构造器
-
可以通过强吻(setAccessible())方法强制访问的构造器,实例化对象,这个是破坏单例模式的途径
-
Constructor类常用方法
- Constuctor[] getConstructors():获取类中所有被public修饰的构造器
- Constructor getConstructor(Class…<?> paramTypes):根据参数类型获取类中某个构造器,该构造器必须被public修饰
- Constructor[] getDeclaredConstructors():获取类中所有构造器
- Constructor getDeclaredConstructor(class…<?> paramTypes):根据参数类型获取对应的构造器
Declared修饰相关说明
- 有Declared修饰的方法:可以获取该类内部包含的所有变量、方法和构造器,但是无法获取继承下来的信息
- 无Declared修饰的方法:可以获取该类中public修饰的变量、方法和构造器,可获取继承下来的信息
Method类(普通方法)
-
包括共有的和私有的修饰方法,且可以继承下来的方法
-
无法获取父类被protect修饰符修饰的方法
-
Method类常用方法
- Method[] getMethods():获取类中被public修饰的所有方法
- Method getMethod(String name, Class…<?> paramTypes):根据名字和参数类型获取对应方法,该方法必须被public修饰
- Method[] getDeclaredMethods():获取所有方法,但无法获取继承下来的方法
- Method getDeclaredMethod(String name, Class…<?> paramTypes):根据名字和参数类型获取对应方法,无法获取继承下来的方法
注解(Annotation)
-
反射常用方法
- Annotation[] getAnnotations():获取该对象上的所有注解
- Annotation getAnnotation(Class annotaionClass):传入注解类型,获取该对象上的特定一个注解
- Annotation[] getDeclaredAnnotations():获取该对象上的显式标注的所有注解,无法获取继承下来的注解
- Annotation getDeclaredAnnotation(Class annotationClass):根据注解类型,获取该对象上的特定一个注解,无法获取继承下来的注解
-
只有注解的@Retension标注为RUNTIME时,才能够通过反射获取到该注解,@Retension 有3种保存策略
- SOURCE:只在**源文件(.java)**中保存,即该注解只会保留在源文件中,编译时编译器会忽略该注解,例如 @Override 注解
- CLASS:保存在字节码文件(.class)中,注解会随着编译跟随字节码文件中,但是运行时不会对该注解进行解析
- RUNTIME:一直保存到运行时,用得最多的一种保存策略,在运行时可以获取到该注解的所有信息
反射的应用场景(常见的)
Spring 实例化对象:当程序启动时,Spring 会读取配置文件applicationContext.xml并解析出里面所有的 标签实例化到IOC容器中。
反射 + 工厂模式:通过反射消除工厂中的多个分支,如果需要生产新的类,无需关注工厂类,工厂类可以应对各种新增的类,反射可以使得程序更加健壮。
JDBC连接数据库:使用JDBC连接数据库时,指定连接数据库的驱动类时用到反射加载驱动类
比较一个对象前后数据的异同可以使用反射
反射的优势及缺陷
优点
- 增加程序的灵活性:面对需求变更时,可以灵活地实例化不同对象
缺陷
- 破坏类的封装性:可以强制访问 private 修饰的信息
- 反射相比直接实例化对象、调用方法、访问变量,中间需要非常多的检查步骤和解析步骤,JVM无法对它们优化。(使用反射会产生比较多的临时对象,导致GC频繁)