反射 Java反射机制提供如下功能: 在运行时判断任意一个对象所属的类 在运行时构造任意一个类的对象 在运行时判段任意一个类所具有的成员变量和方法 在运行时调用任一个对象的方法 在运行时创建新类对象 在使用Java的反射功能时,基本首先都要获取类的Class对象,再通过Class对象获取其他的对象。 1. 动态语言:“程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言”从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C#不是动态语言 2. java的动态机制:但是JAVA有着一个非常突出的动态相关机制:Reflection,用在Java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes。换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods。 3. Class类 a) Java有个Object 类是所有Java 类的继承根源,其内声明了数个应该在所有Java 类中被改写的方法:hashCode()、equals()、clone()、toString()、getClass()等其中getClass()返回一个Class 对象。 b) Class 类十分特殊。它和一般类一样继承自Object,其实体用以表达Java程序运行时的classes和interfaces,。当一个class被加载,或当加载器(class loader)的defineClass()被JVM调用,JVM 便自动产生一个Class 对象,注意它的private Class() {},意指不允许任何人经由编程方式产生Class object。是的,其object 只能由JVM 产生。 4. 获取对应的Class a) 对象.getClass() 如: Class c=”abc”.getClass(); b) Class.getSuperclass() 如:Class c2 =c1.getSuperclass();//获得父类 c) static method--Class.forName()(最常被使用) 如:Classc=Class.forName(“java.util.LinkedList$Entry”); d) 基本类型的包装类的TYPE 如:Classc=Integer.TYPE 返回原生类型,这里是int e) 类名.Class 如Classc=String.Class 5. 获取Fields JAVA 的Class<T>类提供了几个方法获取类的属性。 a) publicField getField(String name) 它反映此 Class 对象所表示的类或接口的指定公共成员 b) publicFileld getDeclaredField(String name) 返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段(包括private) c) publicField[] getFields() 返回一个包含某些 Field 对象的数组,这些对象反映此Class 对象所表示的类或接口的所有可访问公共字段 d) publicField[] getDeclaredField() 返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段(包括private) 6. 注意:如果用getDeclaredField或getDeclaredField获取了private 权限的成员时又想要对其访问时需要用到 暴力反射 Field f=p.getClass().setAccessible(true); 设置可访问性 7. 获取Method a) publicMethod getMethod(String name,Class<?>…parameterType) 返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法 b) publicMethod[] getMethods() 返回一个包含某些 Method 对象的数组,这些对象反映此Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法 c) publicMethod getDeclaredMethod(Stringname,Class<?>…parameterTyprs返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法 d) publicMethod[] getDeclaredMethods() 返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法 8. 注意:调用此函数使用 public Object invoke(Object obj,Object…args) Method method=str.getClass().getMethod(“charAt”,int.class) Method.invoke(str,0);//jdk 1.5 9. 接收数组参数的成员方法的反射 a) 如main(String[] args)函数 Class clazz=Class.forName(“main”,String[].class) 由于jdk1.4和jdk1.5的invoke发生了变化,由1.4的数组参数变成了1.5的可变个数,如果参数本身是非基本类型数组则会将数组进行拆分,所以要对这里进行特殊处理 如 clazz.invoke(null,Object[]{new String[]{“123”,”abc”}})或 calzz.invoke(null,(Object)new String[]{“123”,”abc”}); 10. 获取类的Constructor通过反射机制得到某个类的构造器,然后调用该构造器创建该类的一个实例 a) publicConstructor<T> getConstructor(Class<?>... parameterTypes) 返回一个 Constructor 对象,它反映此Class 对象所表示的类的指定公共构造方法 b) publicConstructor<?>[] getConstructors() 返回一个包含某些 Constructor 对象的数组,这些对象反映此Class 对象所表示的类的所有公共构造方法 c) publicConstructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 返回一个 Constructor 对象,该对象反映此Class 对象所表示的类或接口的指定构造方法 d) publicConstructor<?>[] getDeclaredConstructors() 返回Constructor 对象的一个数组,这些对象反映此 Class 对象表示的类声明的所有构造方法。它们是公共、保护、默认(包)访问和私有构造方法 12. 反射在框架中的开发框架与反射的关系:框架可以通过反射机制预先搭建引用实际未开发好的功能,而工具类是被用户所调用,框架则是调用用户提供的类 13. 用类加载器的方式管理资源和配置文件:通过加载配置文件中的属性加载所配置的类 |