最近闲来无事,刚好看到以前的java反射笔记,这里整理一下,有不足之处还望指出;
在学习java反射机制之前,我们先提出这么一个问题:在Java中,能不能在运行时针对一个Java类,获取它的属性和方法呢?
答案是肯定的,java中解决这个问题就是使用的我们今天需要讲的java反射机制。
java提供一种在运行时动态的获取class的方法和属性以及参数的机制,这种机制就是反射机制。换言之,java可以加载一个在运行时才得知名称的class,并获得它的详细结构(包括权限,继承类等等)。
在JDK中提供API来实现这种机制,API就是reflection APIs。在下文我们将详细了解reflection APIs 。
java内部是怎么实现这种机制的呢?让我们来详细看看Reflection API。java反射相关的API都在java.lang.reflect包中。结构图如下:
member接口:用于获取类的构造方法,字段和成员方法。
AccessibleObject 类:是 Field、Method 和 Constructor 对象的基类。它提供了将反射的对象标记为在使用时取消默认 Java 语言访问控制检查的能力。(通俗解释一下就是获得了更高的使用权限);
Array
类:提供了动态创建和访问 Java 数组的方法。
Constructor类:
提供关于类的单个构造方法的信息以及对它的访问权限
Field:
提供有关类或接口的单个字段的信息,以及对它的动态访问权限。反射的字段可能是一个类(静态)字段或实例字段。
Modifier:类提供了 static
方法和常量,对类和成员访问修饰符进行解码。
Proxy:
提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类。
java反射机制提供了以下功能:
在运行时判断任意一个对象所属的类;
在运行时构造任意一个类的对象;
在运行时判断任意一个类所具有的方法和变量;
在运行时调用任意一个对象的方法;
在运行时创建新类对象;
在java反射机制中,使用反射功能的时候必须先获取类的class对象,再通过class对象获取其他对象(这里的其他对象就是方法对象等)。
那么如何获取类的class对象呢?
1.调用getclass
2.运用.class语法
3.利用静态方法class.forName("类的全类名")
4.使用原始包装类的TYPE语法
这里需要注意的是:这里返回的原始类型,和.class等返回的不一样;
在获取了类的class对象之后,就可以获取类的其他结构。。。
1、获取类的fields对象
java 的 Class<T>类提供了几个方法获取类的属性
通过测试可以看出区别:
可见:
getFields返回的是声明为public的属性(包括父类的属性);
getDeclaredFields返回的是指定类的所有属性(不包括父类的属性);
2、获取类的method对象
java的Class<T>提供如下几个方法获取类的成员方法
注意:区别和获取属性方法的区别相同。
3、获取类的constructor对象
通过反射机制获取指定类的构造器,然后调用这个构造器去创建该类的一个实例
java的Class<T>类提供了几个方法获取类的构造器
新建类的实例
通过反射机制调用类的构造器区创建类的实例,有如下几种方法:
注意:这里就可以看出我们通常所说的类的实例对象,和类的class对象不是同一个概念(通俗解释就是类的class可以生出多个类的实例对象(个人观点,方便理解而已))。
4、调用类的函数
这里调用的才是类的方法,class类调用的是指定类的函数对象(method对象)
如何调用呢?调用方法当然是通过方法对象。
通过Method对象调用它的invoke()实现
invoke(Object obj, Object... args)
对带有指定参数的指定对象调用由此 Method
对象表示的底层方法。
这里一定要注意如果调用的方法是private修饰的,那么必须设置Accessible为true;这里的setAccessible()方法Method父类AccessibleObject的方法。
5、获取和设置类的属性值
class类获取指定类的Filed对象,通过Filed对象调用方法去设置和获取属性值;
在这之前我们先简单说一下代理模式,代理模式就是为其他对象提供一种代理,用以控制对这个对象的访问,这种模式在spring中的AOP中应用广泛;
代理模式的详细解释这里就不赘述了,各位可以去翻阅相关资料。
接下来我们详细看看这个动态代理
这个InvocationHandler类是代理实例的调用处理程序实现的接口。
每个代理实例都具有一个关联的调用处理程序。对代理实例调用方法时,将对方法调用进行编码并将其指派到它的调用处理程序的 invoke
方法。
动态Proxy是这样的一种类:
它是在运行时生成的类(这一点一定要注意),在生成时你必须提供一组接口(interface)给它,然后该class就宣称它实现了这组interface。你可以把这个class的实例当做这些interface中的任何一个来使用。当然这个Dynamic Proxy其实就是一个Proxy(代理类),它并不会为你实现实质性的功能,在使用Proxy的时候必须为它实现invacationHandler接口(这个接口的实现类才会帮我们做具体的工作)。
举例理解Dynamic Proxy
至此java反射机制大概讲解完毕,文中不足希望指出,共同进步。
原文:https://www.cnblogs.com/yizhixiaoxiaoyu/p/10932402.html