反射 在程序运行期间,Java运行时系统始终为所有对象维护一个运行时类型标识,这个信息会跟踪每个对象所属的类。虚拟机利用运行时类型信息选择要执行的正确的方法。 不过,可以使用一个特殊的Java类访问这些信息,保存这些信息的类名为Class。 =================================================================================================================================================================================== 获取Class对像的三种方法 1、使用实例对象 Employee e Class cl = e.getClass(); 2、使用静态方法forName获取类名对应的Class对象 String className = "java.util.Random"; Class cl = Class.forName(className); 3、如果T是任意的Java类型,T.class将代表匹配的类对象 Class cl = Random.class; Class cl2 = int.class; 请注意:一个Class对象实际上表示的是一个类型,这可能是类,也可能不是类。例如:int不是类,但 int.class 是一个Class类型的对象。 虚拟机为每个类型管理一个唯一的Class对象,因此,可以利用==运算法实现两个类型对象的比较, 例如: if(e.getClass == Employee.class) ... 如果e是一个Employee实力,这个测试将通过。与条件e instanceof Employee不同,如果e是某个子类(如Manager)的实例,这个测试将失败。 =================================================================================================================================================================================== ---java.lang.Class类------------------------------------------------------------------------------ static Class forName(String className); 返回一个Class对象,表示名为className的类 Constructor getConstructor(Class... paramterTypes); 生成一个对象,描述有指定参数类型的构造器。 Field getField(String name); Field[] getFields(); Field[] getDeclaredFields(); getFields方法将返回一个包含Field对象的数组,这些对象对应这个类型获其超类的公共字段。getDeclareField方法也返回包含Field对象的数组,这些对象对应这个类的全部字段。 Method[] getMethods(); Method[] getDeclaredMethods(); getMethods将返回所有的公共方法,包含从超类继承来的公共方法;getDeclaredMethods返回这个类或接口的全部方法,但不包括由超类继承的方法。 Constructor[] getConstructors(); Constructor[] getDeclaredConstructors(); getConstructors将返回所有的公共方法,包含从超类继承来的公共方法; getDeclaredConstructors返回这个类或接口的全部方法,但不包括由超类继承的方法。 ---java.lang.reflect.Constructor类------------------------------------------------------------------------------ Object newInstance(Object... params) 将params传递到构造器,来构造这个构造器声明的类的一个新实例。 Class[] getExceptionTypes(); 返回一个Class对象数组,其中各个对象表示这个方法所抛出异常的类型。 int getModifiers(); 返回一个整数,描述这个构造器,方法或字段的修饰符。使用Modifier类中的方法来分析这个返回值。 String getName(); 返回一个表示构造器,方法,或字段的名称 Class[] getParamerTypes() 返回一个Class对象数组,其中各个对象表示参数的类型。 ---java.lang.reflect.Field 类------------------------------------------------------------------------------ int getModifiers(); 返回一个整数,描述这个构造器,方法或字段的修饰符。使用Modifier类中的方法来分析这个返回值。 String getName(); 返回一个表示构造器,方法,或字段的名称; Object get(Object obj); 返回obj对象中用这个Field对象描述的字段值 void set(Object obj, Object newValue); 将obj对象中这个Field对象描述的字段设置为一个新值 ---java.lang.reflect.Method 类------------------------------------------------------------------------------ Class[] getExceptionTypes(); 返回一个Class对象数组,其中各个对象表示这个方法所抛出异常的类型。 int getModifiers(); 返回一个整数,描述这个构造器,方法或字段的修饰符。使用Modifier类中的方法来分析这个返回值。 例如:String modifiers = Modifier.toString(cl.getModifiers()); public static String toString(int mod) { StringBuilder sb = new StringBuilder(); int len; if ((mod & PUBLIC) != 0) sb.append("public "); if ((mod & PROTECTED) != 0) sb.append("protected "); if ((mod & PRIVATE) != 0) sb.append("private "); /* Canonical order */ if ((mod & ABSTRACT) != 0) sb.append("abstract "); if ((mod & STATIC) != 0) sb.append("static "); if ((mod & FINAL) != 0) sb.append("final "); if ((mod & TRANSIENT) != 0) sb.append("transient "); if ((mod & VOLATILE) != 0) sb.append("volatile "); if ((mod & SYNCHRONIZED) != 0) sb.append("synchronized "); if ((mod & NATIVE) != 0) sb.append("native "); if ((mod & STRICT) != 0) sb.append("strictfp "); if ((mod & INTERFACE) != 0) sb.append("interface "); if ((len = sb.length()) > 0) /* trim trailing space */ return sb.toString().substring(0, len-1); return ""; } String getName(); 返回一个表示构造器,方法,或字段的名称 Class[] getParamerTypes() 返回一个Class对象数组,其中各个对象表示参数的类型。 Class getReturnType(); 返回一个用于表示返回类型的Class对象。 public Object invoke(Object obj , Object... params); 调用这个对象描述的方法,传入给定参数,并返回方法的返回值,对于静态方法,传入null作为隐式参数 obj 含有这个方法的对象,params方法的参数 ---java.lang.reflect.Array 类------------------------------------------------------------------------------ static int getLength(Object array); 返回给定数组的长度 static Object newInstance(Class componentType, int length); static Object newInstance(Class componentType , int... lengths); 返回一个有给定类型,给定大小的新数组 =================================================================================================================================================================================== 使用反射可以实现 方法指针,但是不建议这样用,因为使用反射获取方法指针的代码要比直接调用方法的代码慢的多,可以使用接口代替 反射机制的默认行为受限于Java的访问控制。不过,可以调用Field,Method或Constructor对象的setAccessible方法覆盖Java的访问控制。如 f.setAcessible(true); setAccessible方法是AccessibleObject 类中的一个方法,它是Field,Method,Constructor类的公共超类。如果不允许访问,setAccessible调用会抛出一个异常。