什么是反射机制
在运行过程中,对于任何一个类,都能够知道其所有的属性和方法,对于任意一个对象,都能够调用其属性和方法,这种能够动态的获取和调用对象方法的功能,这就是Java的反射机制。
反射的作用
“正向”操作的代码代码在编译之前,就需要明确要运行的类是哪个类
而使用“反向”(反射)创建对象时,只有在代码真正运行的时候,才知道运行的类是哪个
很多场景的情况下,在代码运行之前我们是并不知道要具体使用哪个类的,或者说在运行的时候才来决定到底使用哪个类
// 反射作用
可以设计出更为通用和灵活的架构,很多框架为了保证其通用性,可以根据配置加载不用的类,这时候要用到反射
// 除此之外
动态代理:在不改变目标对象方法的情况下对方法进行增强,比如使用 AOP 拦截某些方法打印日志,这就需要通过反射执行方法中的内容。
注解:利用反射机制,获取注解并执行对应的行为。
反射的优缺点
优点:在运行时动态获取类和对象中的内容,极大地提高系统的灵活性和扩展性;夸张一些说,反射是框架设计的灵魂。
缺点:会有一定的性能损耗,JVM 无法对这些代码进行优化;破坏类的封装性。
应用场景
// 为使用者的服务端添加新的功能
由于为使用着的服务端添加新的功能时,采取在其中new一个含有该新功能的类不够扩展,也难以实现。而反射只要得到(加载)配置文件中的类字符串,再由类的字符串得到该类的字节码文件,然后在得到该类的接口类,最后运行接口类即可运行类中的功能。
反射常用方法
Field :可以使用 get 和 set 方法读取和修改对象的属性; Method :可以使用 invoke() 方法调用对象中的方法; Constructor :可以用 newInstance() 创建新的对象。
获取Class类实例化对象的方式
// 获取Class类实例化对象的方式 1、Class.forName(“全类名”) 使用Class类中的 forName() 静态方法,将字节码文件加载进内存,返回Class对象。 多用于配置文件,将类名定义在配置文件中。读取文件,加载类。 推荐使用这种方式。 2、类名.class 通过类名的属性class获取。 多用于参数的传递。 3、对象.getClass() getClass()方法在Object类中定义着。 多用于对象的获取字节码文件的方式。
获取构造方法
// 获取构造方法 通过Class类中某些方法可以获取对应类中声明的构造方法实例对象 1.Constructor<?>[] getConstructors():返回该Class对象表示类中包含的所有public构造方法(不含继承)所对应的Constructor对象数组。 2.Constructor getConstrutor(Class<?>… parameterTypes):返回与该Class对象表示类中参数列表相匹配的public构造方法(不含继承)对应的Constructor对象。 3.Constructor<?>[] getDeclaredConstructors():返回该Class对象表示类中声明的所有构造方法(不区分访问权限)所对应的Constructor对象数组。 4.Constructor<T> getDeclaredConstructor(Class<?>… parameterTypes):返回与该Class对象表示类中参数列表相匹配的构造方法(不区分访问权限)对应的Constructor对象。
查看构造方法信息
// 查看构造方法信息 通过Constructor类中某些方法可以获取某个构造方法的信息 1.Class<T> getDeclaringClass():返回声明Constructor对象对应构造方法的类的Class对象。 2.int getModifiers():以整数形式返回Constructor对象表示的构造方法的修饰符。 3.String getName() :以字符串形式返回Constructor对象所表示的构造方法的名称。 4.Class<?>[] getParameterTypes():返回由Constructor对象所表示的构造方法的形参类型对应Class对象组成的数组 。如果构造方法没有参数,则数组长度为0。
操作构造方法
// 操作构造方法 通过Constructor类中某些方法可以创建对象 1.void setAccessible(boolean flag):调用构造方法时是否忽略访问权限的影响,true表示忽略,false表示不忽略。 2.T newInstance(Object… initargs):使用此Constructor对象表示的构造方法来创建声明该构造方法类的新对象。initargs为传入该构造方法中的参数,如果该构造方法没有参数,则可设定为null或一个长度为0的数组。
获取成员方法
// 获取成员方法 借助Class类中某些方法可以获取对应类中声明的成员方法实例对象 1.Method[] getMethods():返回该Class对象表示类或接口中所有public方法(含继承的)对应的Method对象数组。 2.Method getMethod(String methodName, Class<?>… parameterTypes):返回与该Class对象表示类或接口中方法名和方法形参类型相匹配的public方法(含继承的)的Method对象。 3.Method[] getDeclaredMethods():返回该Class对象表示类或接口内声明定义的所有访问权限的方法(不含继承的)对应的Method对象数组。 4.Method getDeclaredMethod(String methodName,Class<?>… parameterTypes) :返回与该Class对象表示类或接口中方法名和方法形参类型相匹配方法(不含继承的)对应的Method对象。 // 获取
查看成员方法信息
// 查看成员方法信息 通过Method类中某些方法可以获取某个成员方法的信息 1.Class<?> getDeclaringClass():返回声明Method对象表示方法的类或接口的 Class 对象。 2.int getModifiers():以整数形式返回此Method对象所表示方法的修饰符。应该使用Modifier类中的toString方法对所返回的整数进行解码。 3.Class<?> getReturnType():返回Method对象所表示的方法的返回值类型所对应的Class对象。 4.String getName():返回方法名。 5.Class<?>[] getParameterTypes():返回由Method对象代表方法的形参类型对应Class对象组成的数组。如果方法没有参数,则数组长度为 0。 6.Class<?>[] getExceptionTypes():返回由Method对象表示方法抛出异常类型对应Class对象组成的数组。如果此方法没有在其 throws子句中声明异常,则返回长度为 0 的数组。
操作成员方法
// 操作成员方法 通过Method类中某些方法可以调用成员方法 1.void setAccessible(boolean flag):调用方法时是否忽略访问权限的影响,true表示忽略,false表示不忽略。 2.Object invoke(Object obj, Object… args):调用Method对象指代的方法并返回Object类型结果。obj表示该方法所在类实例,如果方法时静态的则obj可以指定为null; args表示传入该方法的参数,如果方法没有参数,则args数组长度可以为0或null
获取成员变量
// 获取成员变量 通过Class类中某些方法可以获取对应类中声明的成员变量实例对象 1.Field[] getFields():返回该Class对象表示类或接口中所有public属性(含继承的)对应的Field对象数组。 2.Field getField(String fieldName):返回该Class对象表示类或接口中与指定属性名(含继承的)相同的public 属性对应的Field对象。 3.Field[] getDeclaredFields():返回该Class对象表示类或接口内定义的所有属性(不含继承的)对应的Field对象数组。 4.Field getDeclaredField(String fieldName) :返回与该Class对象表示类或接口内定义的属性名(不含继承的)相匹配的属性相对应的Field对象
查看成员变量信息
// 查看成员变量信息 通过Field类中某些方法可以获取某个成员变量的信息 1.Class<?> getDeclaringClass():返回声明Field对象表示字段的类或接口所对应的Class对象。 2.int getModifiers():以整数形式返回Field对象表示的字段的修饰符。 3.Class<?> getType():返回Field对象所表示字段的数据类型所对应的Class对象(推荐)。 4.Type getGenericType():返回此Field对象所表示字段的声明类型。 5.String getName():返回Field对象表示字段的名称。
操作成员变量
// 操作成员变量 通过Field类中某些方法获取及设置成员变量的值 1.void setAccessible(boolean flag):设置或获取属性值时是否忽略访问权限的影响,true表示忽略,false表示不忽略。 2.Object get(Object obj):返回Field表示字段的Object类型的值。obj为该属性所在类创建的对象,如果该属性是静态的,则可设置为null。 3.void set(Object obj, Object value):为Field对象表示属性设置新值。obj为该属性所在类创建的对象,如果该属性为静态的则设置为null;value为该属性新值。