皮皮网

【二手房产网站源码】【溯源码查询机油】【松下空调电源码】getconstructors源码

2024-12-25 14:10:33 来源:iapp邮箱反馈源码

1.反射类的详细简介

getconstructors源码

反射类的详细简介

       åˆå­¦è€…çš„ç±»

       ä½¿ç”¨åå°„的启点总是 java.lang.Class 实例。如果您希望与预先定义的类协作,那么Java语言提供一种直接获得 Class 实例的简便快捷方式:

       Class clas = MyClass.class;

       å½“您使用这一项技术时,装入类涉及的所有工作在幕后进行。但是,如果您需要在运行时从某些外部源读取类名,这种方法并不适合。实际上,您需要使用一个类装入器来查找类信息。以下介绍一种方法:

       // name is 二手房产网站源码the class name to loadClass clas = null;try { clas = Class.forName(name);} catch (ClassNotFoundException ex) { // handle exception case}// use the loaded class

       å¦‚果已经装入了类,您将得到现有的 Class 信息。如果类未被装入,类装入器将现在装入并返回新创建的类实例。

       ç±»çš„反射

       Class 对象为您提供接入类元数据的反射的所有基本hook。这类元数据包括关于类自身的信息,如包和类的父类,以及该类实施的接口。它还包括该类定义的构造函数、字段和方法的详细信息。这些最后的项目都是编程中最经常使用的项目,因此我将在本小节的稍后部分给出一些与它们协作的实例。

       å¯¹äºŽä»¥ä¸‹ä¸‰ç±»ç»„件中的任何一类来说 -- 构造函数、字段和方法 -- java.lang.Class 提供四种独立的反射调用,以不同的方式来获得信息。调用都遵循一种标准格式。以下是用于查找构造函数的一组反射调用:

       Constructor getConstructor(Class[] params) -- 获得使用特殊的参数类型的公共构造函数,

       Constructor[] getConstructors() -- 获得类的所有公共构造函数

       Constructor getDeclaredConstructor(Class[] params) -- 获得使用特定参数类型的构造函数(与接入级别无关)

       Constructor[] getDeclaredConstructors() -- 获得类的所有构造函数(与接入级别无关)

       æ¯ç±»è¿™äº›è°ƒç”¨éƒ½è¿”回一个或多个 java.lang.reflect.Constructor 函数。这种 Constructor 类定义 newInstance 方法,它采用一组对象作为其唯一的参数,然后返回新创建的原始类实例。该组对象是用于构造函数调用的参数值。作为解释这一工作流程的实例,假设您有一个 TwoString 类和一个使用一对 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 = TwoString.class.getConstructor(types); Object[] args = new Object[] { a, b }; TwoString ts = cons.newInstance(args);

       æ¸…单2中的代码忽略了不同反射方法抛出的多种可能选中的例外类型。例外在 Javadoc API 描述中详细记录,因此为了简明起见,我将在所有程序实例中忽略它们。

       å°½ç®¡æˆ‘在讨论构造函数主题,Java编程语言还定义了一种您可以用来使用 无参数(或缺省)构造函数创建类的一个实例的特殊快捷方式。这种快捷方式嵌入到 Class 定义中,如下:

       Object newInstance() -- 使用缺省函数创建新的实例

       å³ä½¿è¿™ç§æ–¹æ³•åªå…è®¸æ‚¨ä½¿ç”¨ä¸€ç§ç‰¹æ®Šçš„构造函数,如果这正是您需要的,那么它将提供一种非常方便的快捷方式。当与JavaBeans协作时这项技术尤其有用,JavaBeans需要定义公共、无参数构造函数。

       é€šè¿‡åå°„增加字段

       èŽ·å¾—字段信息的 Class 反射调用不同于那些用于接入构造函数的调用,在参数类型数组中使用了字段名:

       Field getField(String name) -- 获得命名的公共字段

       Field[] getFields() -- 获得类的所有公共字段

       Field getDeclaredField(String name) -- 获得类声明的命名的字段

       Field[] getDeclaredFields() -- 获得类声明的所有字段

       å°½ç®¡ä¸Žæž„造函数调用类似,在字段方面仍存在一个重要的区别:前两个变量返回可以通过类接入的公共字段的信息 -- 即使它们来自于祖先类。后两个变量返回类直接声明的字段的信息 -- 与字段的接入类型无关。

       è°ƒç”¨è¿”回的 java.lang.reflect.Field 实例定义所有主类型的 getXXX 和 setXXX 方法,

       æ–‡ç« å‡ºå¤„:/course/3_program/java/javashl//.html

       ä»¥åŠä¸Žå¯¹è±¡å¼•ç”¨åä½œçš„通用 get 和 set 方法。您可以根据实际的字段类型自行选择一种适当的方法,而 getXXX 方法将自动处理扩展转换(如使用 getInt 方法来检索一个字节值)。

       æ¸…单3显示使用字段反射方法的一个实例,以方法的格式根据名称增加对象的 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 方法来查找类信息,然后直接在该类中查找命名的字段。

       é€šè¿‡åå°„增加方法

       èŽ·å¾—方法信息的 Class 反射调用与用于构造函数和字段的调用非常类似:

       Method getMethod(String name, Class[] params) -- 使用特定的参数类型,获得命名的公共方法

       Method[] getMethods() -- 获得类的所有公共方法

       Method getDeclaredMethod(String name, Class[] params) -- 使用特写的参数类型,获得类声明的命名的方法

       Method[] getDeclaredMethods() -- 获得类声明的所有方法

       ä¸Žå­—段调用一样,前两个变量返回可以通过类接入的公共方法的信息 -- 即使它们来自于祖先类。后两个变量返回类声明的方法的信息,与方法的接入类型无关。

       è°ƒç”¨è¿”回的 java.lang.reflect.Method 实例定义一种 invoke 方法,您可以用来在正在定义的类的一个实例上调用方法。这种 invoke 方法使用两个参数,为调用提供类实例和参数值数组。

       æ¸…单4进一步阐述字段实例,显示反射正在运行的方法的一个实例。这种方法增加一个定义有 get 和 set 方法的 int JavaBean属性。例如,如果对象为一个整数 count 值定义了 getCount 和 setCount 方法,您可以在一次调用中向该方法传递“count”作为 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.invoke(obj, new Object[0]); int value = ((Integer)result).intValue() + 1; mname = set + prop; types = new Class[] { int.class }; method = obj.getClass().getMethod(mname, types); method.invoke(obj, new Object[] { new Integer(value) }); return value;}

       ä¸ºäº†éµå¾ªJavaBeans惯例,我把属性名的首字母改为大写,然后预先考虑 get 来创建读方法名, set 来创建写方法名。JavaBeans读方法仅返回值,而写方法使用值作为唯一的参数,因此我规定方法的参数类型以进行匹配。最后,该惯例要求方法为公共,因此我使用查找格式,查找类上可调用的公共方法。

       è¿™ä¸€å®žä¾‹æ˜¯ç¬¬ä¸€ä¸ªæˆ‘使用反射传递主值的实例,因此现在我们来看看它是如何工作的。基本原理很简单:无论什么时候您需要传递主值,只需用相应封装类的一个实例(在 java.lang 包中定义)来替换该类主值。这可以应用于调用和返回。因此,当我在实例中调用 get 方法时,我预计结果为实际 int 属性值的 java.lang.Integer 封装。

       åå°„数组

       æ•°ç»„是Java编程语言中的对象。与所有对象一样,它们都有类。如果您有一个数组,使用标准 getClass 方法,您可以获得该数组的类,就象任何其它对象一样。但是, 不通过现有的实例来获得类不同于其它类型的对象。即使您有一个数组类,您也不能直接对它进行太多的操作 -- 反射为标准类提供的构造函数接入不能用于数组,而且数组没有任何可接入的字段,只有基本的 java.lang.Object 方法定义用于数组对象。

       æ•°ç»„的特殊处理使用 java.lang.reflect.Array 类提供的静态方法的集合。该类中的方法使您能够创建新数组,获得数组对象的长度,读和写数组对象的索引值。

       æ¸…单5显示了一种重新调整现有数组大小的有效方法。它使用反射来创建相同类型的新数组,然后在返回新数组之前,在老数组中复制所有数据。

       æ¸…单 5:通过反射来扩展一个数组

       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;}

       å®‰å…¨æ€§å’Œåå°„

       åœ¨å¤„理反射时安全性是一个较复杂的问题。反射经常由框架型代码使用,由于这一点,您可能希望框架能够全面接入您的代码,无需考虑常规的接入限制。但是,在其它情况下,不受控制的接入会带来严重的安全性风险,如当代码在不值得信任的代码共享的环境中运行时。

       ç”±äºŽè¿™äº›äº’相矛盾的需求,Java编程语言定义一种多级别方法来处理反射的安全性。基本模式是对反射实施与应用于源代码接入相同的的限制:

       ä»Žä»»æ„ä½ç½®åˆ°ç±»å…¬å…±ç»„件的接入

       ç±»è‡ªèº«å¤–部无任何到私有组件的接入

       å—保护和打包(缺省接入)组件的有限接入

       ä¸è¿‡ï¼è‡³å°‘某些时候,围绕这些限制有一种简单的方法。我在前面实例中使用的 Constructor 、 Field 和 Method 类都扩展了一个普通的基本类-- java.lang.reflect.AccessibleObject 类。该类定义一种 setAccessible 方法,使您能够启动或关闭对这些类中其中一个类的实例的接入检测。唯一的问题在于如果使用了安全性管理器,它将检测正在关闭接入检测的代码是否许可了这样做。如果未许可,安全性管理器抛出一个例外。

       æ¸…单6展示了一个程序,在 清单 1 TwoString 类的一个实例上使用反射来显示安全性正在运行:

       æ–‡ç« å‡ºå¤„:/course/3_program/java/javashl//_2.html