ImageVerifierCode 换一换
格式:DOCX , 页数:10 ,大小:21.20KB ,
资源ID:16652374      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/16652374.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(对JAVA反射机制的认识Word文件下载.docx)为本站会员(b****3)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

对JAVA反射机制的认识Word文件下载.docx

1、Constructor getDeclaredConstructor(Class params) - 获得使用特定参数类型的构造函数(与接入级别无关) Constructor getDeclaredConstructors() - 获得类的所有构造函数(与接入级别无关) 每类这些调用都返回一个或多个 java.lang.reflect.Constructor 函数。这种 Constructor 类定义 newInstance 方法,它采用一组对象作为其唯一的参数,然后返回新创建的原始类实例。该组对象是用于构造函数调用的参数值。作为解释这一工作流程的实例,假设您有一个 TwoString 类和一

2、个使用一对 String s的构造函数,如清单1所示:清单1:从一对字符串创建的类public class TwoString private String m_s1, m_s2; public TwoString(String s1, String s2) m_s1 = s1; m_s2 = s2; 清单2中的代码获得构造函数并使用它来创建使用 String s a 和 b 的 TwoString 类的一个实例:清单2:构造函数的反射调用 Class types = new Class String.class, String.class ; Constructor cons = TwoSt

3、ring.class.getConstructor(types); Object args = new Object , ; TwoString ts = cons.newInstance(args);清单2中的代码忽略了不同反射方法抛出的多种可能选中的例外类型。例外在 Javadoc API 描述中详细记录,因此为了简明起见,我将在所有程序实例中忽略它们。尽管我在讨论构造函数主题,Java编程语言还定义了一种您可以用来使用 无参数(或缺省)构造函数创建类的一个实例的特殊快捷方式。这种快捷方式嵌入到 Class 定义中,如下:Object newInstance() - 使用缺省函数创建新的实

4、例即使这种方法只允许您使用一种特殊的构造函数,如果这正是您需要的,那么它将提供一种非常方便的快捷方式。当与JavaBeans协作时这项技术尤其有用,JavaBeans需要定义公共、无参数构造函数。2.2. 基于字段的反射字段,可以理解为类的属性。 获得字段信息的 Class 反射调用不同于那些用于接入构造函数的调用,在参数类型数组中使用了字段名:Field getField(String name) - 获得命名的公共字段 Field getFields() - 获得类的所有公共字段 Field getDeclaredField(String name) - 获得类声明的命名的字段 Field

5、 getDeclaredFields() - 获得类声明的所有字段 尽管与构造函数调用类似,在字段方面仍存在一个重要的区别:前两个变量返回可以通过类接入的公共字段的信息 - 即使它们来自于祖先类。后两个变量返回类直接声明的字段的信息 - 与字段的接入类型无关。调用返回的 java.lang.reflect.Field 实例定义所有主类型的 getXXX 和 setXXX 方法,以及与对象引用协作的通用 get 和 set 方法。您可以根据实际的字段类型自行选择一种适当的方法,而 getXXX 方法将自动处理扩展转换(如使用 getInt 方法来检索一个字节值)。清单3显示使用字段反射方法的一个

6、实例,以方法的格式根据名称增加对象的 int 字段 :清单3:通过反射增加一个字段public int incrementField(String name, Object obj) throws. Field field = obj.getClass().getDeclaredField(name); int value = field.getInt(obj) + 1; field.setInt(obj, value); return value;这种方法开始展示了反射带来的某些灵活性。与特定的类协作不同, incrementField 使用传 入的对象的 getClass 方法来查找类信息

7、,然后直接在该类中查找命名的字段。2.3. 基于方法的反射获得方法信息的 Class 反射调用与用于构造函数和字段的调用非常类似:Method getMethod(String name, Class params) - 使用特定的参数类型,获得命名的公共方法 Method getMethods() - 获得类的所有公共方法 Method getDeclaredMethod(String name, Class params) - 使用特写的参数类型,获得类声明的命名的方法 Method getDeclaredMethods() - 获得类声明的所有方法 与字段调用一样,前两个变量返回可以通过

8、类接入的公共方法的信息 - 即使它们来自于祖先类。后两个变量返回类声明的方法的信息,与方法的接入类型无关。调用返回的 java.lang.reflect.Method 实例定义一种 invoke 方法,您可以用来在正在定义的类的一个实例上调用方法。这种 invoke 方法使用两个参数,为调用提供类实例和参数值数组。清单4进一步阐述字段实例,显示反射正在运行的方法的一个实例。这种方法增加一个定义有 get 和 set 方法的 int JavaBean属性。例如,如果对象为一个整数 count 值定义了 getCount 和 setCount 方法,您可以在一次调用中向该方法传递“count”作为

9、 name 参数,以增加该值。清单4:通过反射增加一个JavaBean 属性public int incrementProperty(String name, Object obj) String prop = Character.toUpperCase(name.charAt(0) + name.substring(1); String mname = get + prop; Class types = new Class ; Method method = obj.getClass().getMethod(mname, types); Object result = method.invo

10、ke(obj, new Object0); int value = (Integer)result).intValue() + 1; mname = set types = new Class int.class ; method = obj.getClass().getMethod(mname, types); method.invoke(obj, new Object new Integer(value) );为了遵循JavaBeans惯例,我把属性名的首字母改为大写,然后预先考虑 get 来创建读方法名, set 来创建写方法名。JavaBeans读方法仅返回值,而写方法使用值作为唯一的

11、参数,因此我规定方法的参数类型以进行匹配。最后,该惯例要求方法为公共,因此我使用查找格式,查找类上可调用的公共方法。这一实例是第一个我使用反射传递主值的实例,因此现在我们来看看它是如何工作的。基本原理很简单:无论什么时候您需要传递主值,只需用相应封装类的一个实例(在 java.lang 包中定义)来替换该类主值。这可以应用于调用和返回。因此,当我在实例中调用 get 方法时,我预计结果为实际 int 属性值的 java.lang.Integer 封装。2.4. 数组的反射 数组是Java编程语言中的对象。与所有对象一样,它们都有类。如果您有一个数组,使用标准 getClass 方法,您可以获得

12、该数组的类,就象任何其它对象一样。但是, 不通过现有的实例来获得类不同于其它类型的对象。即使您有一个数组类,您也不能直接对它进行太多的操作 - 反射为标准类提供的构造函数接入不能用于数组,而且数组没有任何可接入的字段,只有基本的 java.lang.Object 方法定义用于数组对象。数组的特殊处理使用 java.lang.reflect.Array 类提供的静态方法的集合。该类中的方法使您能够创建新数组,获得数组对象的长度,读和写数组对象的索引值。清单5显示了一种重新调整现有数组大小的有效方法。它使用反射来创建相同类型的新数组,然后在返回新数组之前,在老数组中复制所有数据。清单 5:通过反射

13、来扩展一个数组public Object growArray(Object array, int size) Class type = array.getClass().getComponentType(); Object grown = Array.newInstance(type, size); System.arraycopy(array, 0, grown, 0, Math.min(Array.getLength(array), size); return grown;3. 实例中的经典运用1. 得到某个对象的属性public Object getProperty(Object own

14、er, String fieldName) throws Exception Class ownerClass = owner.getClass(); Field field = ownerClass.getField(fieldName); Object property = field.get(owner); return property; Class ownerClass = owner.getClass():得到该对象的Class。Field field = ownerClass.getField(fieldName):通过Class得到类声明的属性。Object property

15、= field.get(owner):通过对象得到该属性的实例,如果这个属性是非公有的,这里会报IllegalAccessException。2. 得到某个类的静态属性public Object getStaticProperty(String className, String fieldName) throws Exception Class ownerClass = Class.forName(className); Object property = field.get(ownerClass);Class ownerClass = Class.forName(className) :首

16、先得到这个类的Class。和上面一样,通过Class得到类声明的属性。Object property = field.get(ownerClass) :这里和上面有些不同,因为该属性是静态的,所以直接从类的Class里取。3. 执行某对象的方法public Object invokeMethod(Object owner, String methodName, Object args) throws Exception Class argsClass = new Classargs.length; for (int i = 0, j = args.length; i j; i+) argsCl

17、assi = argsi.getClass(); Method method = ownerClass.getMethod(methodName, argsClass); return method.invoke(owner, args);Class owner_class = owner.getClass() :首先还是必须得到这个对象的Class。36行:配置参数的Class数组,作为寻找Method的条件。Method method = ownerClass.getMethod(methodName, argsClass):通过Method名和参数的Class数组得到要执行的Method

18、。method.invoke(owner, args):执行该Method,invoke方法的参数是执行这个方法的对象,和参数数组。返回值是Object,也既是该方法的返回值。4. 执行某个类的静态方法public Object invokeStaticMethod(String className, String methodName, Object args) throws Exception return method.invoke(null, args);基本的原理和实例3相同,不同点是最后一行,invoke的一个参数是null,因为这是静态方法,不需要借助实例运行。5. 新建实例pu

19、blic Object newInstance(String className, Object args) throws Exception Class newoneClass = Class.forName(className); Constructor cons = newoneClass.getConstructor(argsClass); return cons.newInstance(args);这里说的方法是执行带参数的构造函数来新建实例的方法。如果不需要参数,可以直接使用newoneClass.newInstance()来实现。Class newoneClass = Class

20、.forName(className):第一步,得到要构造的实例的Class。第6第10行:得到参数的Class数组。Constructor cons = newoneClass.getConstructor(argsClass):得到构造子。cons.newInstance(args):新建实例。6. 判断是否为某个类的实例public boolean isInstance(Object obj, Class cls) return cls.isInstance(obj);7. 得到数组中的某个元素public Object getByArray(Object array, int inde

21、x) return Array.get(array,index);4. 性能问题和缺点反射是一种强大的工具,但也存在一些不足。一个主要的缺点是对性能有影响。使用反射基本上是一种解释操作,您可以告诉JVM您希望做什么并且它满足您的要求。这类操作总是慢于只直接执行相同的操作。为了阐述使用反射的性能成本,我为本文准备了一组基准程序。清单6是字段接入性能测试的一个摘用,包括基本的测试方法。每种方法测试字段接入的一种形式 - accessSame 与同一对象的成员字段协作, accessOther 使用可直接接入的另一对象的字段, accessReflection 使用可通过反射接入的另一对象的字段。在

22、每种情况下,方法执行相同的计算 - 循环中简单的加/乘顺序。清单 6:字段接入性能测试代码public int accessSame(int loops) m_value = 0; for (int index = 0; index loops; index+) m_value = (m_value + ADDITIVE_VALUE) * MULTIPLIER_VALUE; return m_value;public int accessReference(int loops) TimingClass timing = new TimingClass(); timing.m_value = (

23、timing.m_value + ADDITIVE_VALUE) * return timing.m_value;public int accessReflection(int loops) throws Exception try Field field = TimingClass.class. getDeclaredField(m_value); int value = (field.getInt(timing) + ADDITIVE_VALUE) * MULTIPLIER_VALUE; field.setInt(timing, value); catch (Exception ex) S

24、ystem.out.println(Error using reflection throw ex;测试程序重复调用每种方法,使用一个大循环数,从而平均多次调用的时间衡量结果。平均值中不包括每种方法第一次调用的时间,因此初始化时间不是结果中的一个因素。在为本文进行的测试中,每次调用时我使用1000万的循环数,在1GHz PIIIm系统上运行。三个不同Linux JVM的计时结果如图1所示。所有测试使用每个JVM的缺省设置。图 1:字段接入时间上表的对数尺度可以显示所有时间,但减少了差异看得见的影响。在前两副图中(Sun JVM),使用反射的执行时间超过使用直接接入的1000倍以上。通过比较,I

25、BM JVM可能稍好一些,但反射方法仍旧需要比其它方法长700倍以上的时间。任何JVM上其它两种方法之间时间方面无任何显著差异,但IBM JVM几乎比Sun JVM快一倍。最有可能的是这种差异反映了Sun Hot Spot JVM的专业优化,它在简单基准方面表现得很糟糕。 反射有两个缺点。第一个是性能问题。当用于字段和方法接入时反射要远慢于直接代码。性能问题的程度取决于程序中是如何使用反射的。如果它作为程序运行中相对很少涉及的部分,缓慢的性能将不会是一个问题。即使测试中最坏情况下的计时图显示的反射操作只耗用几微秒。仅反射在性能关键的应用的核心逻辑中使用时性能问题才变得至关重要。许多应用更严重的一个缺点是使用反射会模糊程序内部实际要发生的事情。程序人员希望在源代码中看到程序的逻辑,反射等绕过了源代码的技术会带来维护问题。反射代码比相应的直接代码更复杂,正如性能比较的代码实例中看到的一样。解决这些问题的最佳方案是保守地使用反射- 仅在它可以真正增加灵活性的地方 - 记录其在目标类中的使用。

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1