四川建设厅官方网站是多少,广东阳江房产网,wordpress基础服务器,上海集团网址在了解反射前#xff0c;我们先要知道一些相关知识
Class类
Class类的实例表示java应用运行时的类或接口#xff0c;每个java类运行时都在JVM里表现为一个class对象#xff0c;可通过类名.class、类型.getClass()、Class.forName(类名)等方法获取class对象。 …在了解反射前我们先要知道一些相关知识
Class类
Class类的实例表示java应用运行时的类或接口每个java类运行时都在JVM里表现为一个class对象可通过类名.class、类型.getClass()、Class.forName(类名)等方法获取class对象。
类的加载流程可在另一篇文章查看。 定义
Java 反射Reflection是指在运行时动态地获取类的信息、调用方法、获取属性等从而实现运行时的类型检查、动态代码生成、设置和操作类的信息等功能。动态获取的信息以及动态调用对象。有两个特点
1、对于任意一个类都能够知道这个类的所有属性和方法
2、对于任意一个对象都能够调用它的任意一个方法和属性 通俗的说反射就是把java类中的各种成分映射成一个个的Java对象。
一个类有成员变量、方法、构造方法、包等等信息利用反射技术可以对一个类进行解剖把个个组成部分映射成一个个对象。
需要注意的是
反射机制的使用可能会带来一些性能上的损失因为它需要在运行时进行类型检查和方法调用。此外反射机制还可能会导致安全漏洞因为它可以执行任意代码。因此在实际开发中需要谨慎使用反射并且根据具体情况选择是否使用反射。 反射的实现原理
基于java虚拟机的动态加载并依赖于 Class 类java虚拟机在运行时动态的加载类并生成对应的class对象这个对象包含了类的所有信息可通过class对象获取类的信息进而实现对类的操作。
使用时大致可分为几个步骤
反射获取类实例 - 反射获取方法 - 调用method.invoke()方法
1、获取 Class 对象通过 Class.forName() 方法获取要反射的类的 Class 对象。
2、获取 Method 对象通过getMethod() 等方法获取要调用的方法的 Method 对象。
3、调用方法method.invoke() 方法调用该方法最终是由jvm执行invoke0()执行可获取返回值。
4、获取 Field 对象通过getField() 等方法获取要访问的属性的 Field 对象。
5、设置属性值通过 Field.setAccessible(true) 方法将属性设置为可访问。然后可以通过 Field.get(object) 方法获取该属性的值。
下面我们一步步分析一波。
Class类对象的获取
在类加载的时候jvm会创建一个class对象获取class对象的方式的主要有三种:
根据类名类名.class根据对象对象.getClass()根据全限定类名Class.forName(全限定类名) 方法名 说明 forName() (1)获取Class对象的一个引用但引用的类还没有加载(该类的第一个对象没有生成)就加载了这个类。 (2)为了产生Class引用调用forName()会立即就进行初始化。 Object-getClass() 获取Class对象的一个引用返回表示该对象的实际类型的Class引用。 getName() 取全限定的类名(包括包名)即类的完整名字。 getSimpleName() 获取类名(不包括包名) getCanonicalName() 获取全限定的类名(包括包名),大多数情况下和getName一样 isInterface() 判断Class对象是否是表示一个接口 getInterfaces() 返回Class对象数组表示Class对象所引用的类所实现的所有接口。 getSupercalss() 返回Class对象表示Class对象所引用的类所继承的直接基类。应用该方法可在运行时发现一个对象完整的继承结构。 newInstance() 返回一个Oject对象是实现“虚拟构造器”的一种途径。使用该方法创建的类必须带有无参的构造器。 getFields() 获得某个类的所有的公共public的字段包括继承自父类的所有公共字段。 类似的还有getMethods和getConstructors。 getDeclaredFields 获得某个类的自己声明的字段即包括public、private和proteced默认但是不包括父类声明的任何字段。类似的还有getDeclaredMethods和getDeclaredConstructors。
首先调用了 java.lang.Class 的静态方法forName()获取反射获取类信息调用到new instance
newInstance() 主要做了三件事 权限检测如果不通过直接抛出异常 查找无参构造器并将其缓存起来 调用具体方法的无参构造方法生成实例并返回
然后是获取构造器的过程
先获取所有的constructors, 然后通过进行参数类型比较找到匹配后通过 ReflectionFactory copy一份constructor返回否则抛出 NoSuchMethodException; Constructor类及其用法
Constructor 类表示的是Class 对象所表示的类的构造方法利用它可以在运行时动态创建对象。 方法返回值 方法名称 方法说明 static Class forName(String className) 返回与带有给定字符串名的类或接口相关联的 Class 对象。 Constructor getConstructor(Class... parameterTypes) 返回指定参数类型、具有public访问权限的构造函数对象 Constructor[] getConstructors() 返回所有具有public访问权限的构造函数的Constructor对象数组 Constructor getDeclaredConstructor(Class... parameterTypes) 返回指定参数类型、所有声明的包括private构造函数对象 Constructor[] getDeclaredConstructors() 返回所有声明的包括private构造函数对象 T newInstance() 调用无参构造器创建此 Class 对象所表示的类的一个新实例。 方法返回值 方法名称 方法说明 Class getDeclaringClass() 返回 Class 对象该对象表示声明由此 Constructor 对象表示的构造方法的类,其实就是返回真实类型不包含参数 Type[] getGenericParameterTypes() 按照声明顺序返回一组 Type 对象返回的就是 Constructor对象构造函数的形参类型。 String getName() 以字符串形式返回此构造方法的名称。 Class[] getParameterTypes() 按照声明顺序返回一组 Class 对象即返回Constructor 对象所表示构造方法的形参类型 T newInstance(Object... initargs) 使用此 Constructor对象表示的构造函数来创建新实例 String toGenericString() 返回描述此 Constructor 的字符串其中包括类型参数。
Field类及其用法
Field 表示Class对象所表示的类的成员变量通过它可以在运行时动态修改成员变量的属性值(包含private)。
Field 类提供有关类或接口的单个字段的信息以及对它的动态访问权限。
通过Class类的提供的方法来获取代表字段信息的Field对象 方法返回值 方法名称 方法说明 Field getDeclaredField(String name) 获取指定name名称的(包含private修饰的)字段不包括继承的字段 Field[] getDeclaredFields() 获取Class对象所表示的类或接口的所有(包含private修饰的)字段,不包括继承的字段 Field getField(String name) 获取指定name名称、具有public修饰的字段包含继承字段 Field[] getFields() 获取修饰符为public的字段包含继承字段 方法返回值 方法名称 方法说明 void set(Object obj, Object value) 将指定对象变量上此 Field 对象表示的字段设置为指定的新值。 Object get(Object obj) 返回指定对象上此 Field 表示的字段的值 Class getType() 返回一个 Class 对象它标识了此Field 对象所表示字段的声明类型。 boolean isEnumConstant() 如果此字段表示枚举类型的元素则返回 true否则返回 false String toGenericString() 返回一个描述此 Field包括其一般类型的字符串 String getName() 返回此 Field 对象表示的字段的名称 Class getDeclaringClass() 返回表示类或接口的 Class 对象该类或接口声明由此 Field 对象表示的字段 void setAccessible(boolean flag) 将此对象的 accessible 标志设置为指示的布尔值,即设置其可访问性
Method类及其用法
Method 表示Class对象所表示的类的成员方法通过它可以动态调用对象的方法(包含private)。
Method 提供关于类或接口上单独某个方法以及如何访问该方法的信息。 方法返回值 方法名称 方法说明 Method getDeclaredMethod(String name, Class... parameterTypes) 返回一个指定参数的Method对象该对象反映此 Class 对象所表示的类或接口的指定已声明方法。 Method[] getDeclaredMethods() 返回 Method 对象的一个数组这些对象反映此 Class 对象表示的类或接口声明的所有方法包括公共、保护、默认包访问和私有方法但不包括继承的方法。 Method getMethod(String name, Class... parameterTypes) 返回一个 Method 对象它反映此 Class 对象所表示的类或接口的指定公共成员方法。 Method[] getMethods() 返回一个包含某些 Method 对象的数组这些对象反映此 Class 对象所表示的类或接口包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口的公共 member 方法。 方法返回值 方法名称 方法说明 Object invoke(Object obj, Object... args) 对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。 Class getReturnType() 返回一个 Class 对象该对象描述了此 Method 对象所表示的方法的正式返回类型,即方法的返回类型 Type getGenericReturnType() 返回表示由此 Method 对象所表示方法的正式返回类型的 Type 对象也是方法的返回类型。 Class[] getParameterTypes() 按照声明顺序返回 Class 对象的数组这些对象描述了此 Method 对象所表示的方法的形参类型。即返回方法的参数类型组成的数组 Type[] getGenericParameterTypes() 按照声明顺序返回 Type 对象的数组这些对象描述了此 Method 对象所表示的方法的形参类型的也是返回方法的参数类型 String getName() 以 String 形式返回此 Method 对象表示的方法名称即返回方法的名称 boolean isVarArgs() 判断方法是否带可变参数如果将此方法声明为带有可变数量的参数则返回 true否则返回 false。 String toGenericString() 返回描述此 Method 的字符串包括类型参数。
获取方法也一样 1. 获取所有方法列表 2. 根据方法名称和方法列表选出符合要求的方法 3. 如果没有找到相应方法抛出异常否则返回对应方法
后面调取invoke时是通过 MethodAccessor 进行调用的而 MethodAccessor 是个接口在第一次时调用 acquireMethodAccessor() 进行新创建。
进行 ma.invoke(obj, args); 调用时调用 DelegatingMethodAccessorImpl.invoke();
最后被委托到 NativeMethodAccessorImpl.invoke() 最后再贴一张网络图