1 / 25

java 的反射机制

java 的反射机制. 反射 类动态装入与检查 使用反射生成与使用对象. 在 Java 运行时环境中,对于任意一个类,能否知道这个类有哪些属性和方法?对于任意一个对象,能否调用它的任意一个方法?答案是肯定的。这种动态获取类的信息,以及动态调用对象的方法的功能来自于 Java 语言的反射( Reflection )机制。 Java 反射机制主要提供了以下功能: ◆在运行时判断任意一个对象所属的类; ◆在运行时构造任意一个类的对象; ◆在运行时判断任意一个类所具有的成员变量和方法; ◆在运行时调用任意一个对象的方法; ◆生成动态代理。.

toby
Download Presentation

java 的反射机制

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. java 的反射机制 • 反射 • 类动态装入与检查 • 使用反射生成与使用对象

  2. 在Java运行时环境中,对于任意一个类,能否知道这个类有哪些属性和方法?对于任意一个对象,能否调用它的任意一个方法?答案是肯定的。这种动态获取类的信息,以及动态调用对象的方法的功能来自于Java语言的反射(Reflection)机制。Java反射机制主要提供了以下功能:在Java运行时环境中,对于任意一个类,能否知道这个类有哪些属性和方法?对于任意一个对象,能否调用它的任意一个方法?答案是肯定的。这种动态获取类的信息,以及动态调用对象的方法的功能来自于Java语言的反射(Reflection)机制。Java反射机制主要提供了以下功能: • ◆在运行时判断任意一个对象所属的类;◆在运行时构造任意一个类的对象;◆在运行时判断任意一个类所具有的成员变量和方法;◆在运行时调用任意一个对象的方法;◆生成动态代理。

  3. 在JDK中,主要由以下类来实现Java反射机制,这些类都位于java.lang.reflect包中。在JDK中,主要由以下类来实现Java反射机制,这些类都位于java.lang.reflect包中。 • ◆Class类:代表一个类。◆Field类:代表类的成员变量(成员变量也称为类的属性)。◆Method类:代表类的方法。◆Constructor类:代表类的构造方法。◆Array类:提供了动态创建数组,以及访问数组元素的静态方法。

  4. Class与类动态装入 • 当真正需要使用一個类时系统才会装入它 • java.lang.Class是Java应用程序在运行时装入类和接口的实例 • Class只能由系统建立对象 • 我们可以通过Object的getClass()方法來取得某个对象对应Class对象

  5. String name = "hello"; Class stringClass = name.getClass(); System.out.println("类名:" + stringClass.getName()); System.out.println("是否为接口:" + stringClass.isInterface()); System.out.println("是否为基本类型:" + stringClass.isPrimitive()); System.out.println("是否为数组:" + stringClass.isArray()); System.out.println("父类名:" + stringClass.getSuperclass().getName()); Class stringClass = String.class;

  6. Class的信息是在编译时确定的 • 执行时JVM在使用某个类时,会先检查对应的Class对象是否装入 • 如果沒有装入,则会寻找对应的.class档案并装入

  7. 一个类在JVM中只会有一个Class实例 • 每个类的实例都会记得自己是由哪个Class实例所生成 • 可使用getClass()或.class来取得Class实例

  8. import java.lang.reflect.*;public class DumpMethods {public static void main(String args[]) throws Exception{//加载并初始化命令行参数指定的类 Class classType = Class.forName(args[0]);//获得类的所有方法Method methods[] = classType.getDeclaredMethods();for(int i = 0; i < methods.length; i++)System.out.println(methods[i].toString());}}

  9. 数组是对象,也有其对应的Class实例 System.out.println(boolean.class); System.out.println(void.class); int[] iarr = new int[10]; System.out.println(iarr.getClass().toString()); double[] darr = new double[10]; System.out.println(darr.getClass().toString()); boolean void class [I class [D

  10. 从Class中获得信息 • Class表示所装入的类,取得Class之后,就可以取得该类相关信息 • 包对应的是java.lang.Package • 构造方法的对应的是java.lang.reflect.Constructor • 成员方法对应的是java.lang.reflect.Method • 属性对应的是java.lang.reflect.Field

  11. try { Class c = Class.forName(args[0]); Package p = c.getPackage(); System.out.println(p.getName()); } catch(ArrayIndexOutOfBoundsException e) { System.out.println("没有指定类"); } catch(ClassNotFoundException e) { System.out.println("找不到指定类"); }

  12. Class c = Class.forName(args[0]); Package p = c.getPackage(); System.out.printf("package %s;%n", p.getName()); // 取得类型修饰,是否是class、interface int m = c.getModifiers(); System.out.print(Modifier.toString(m) + " "); // 如果是接口 if(Modifier.isInterface(m)) { System.out.print("interface "); } else { System.out.print("class "); } System.out.println(c.getName() + " {");

  13. // 获得声明的成员 Field[] fields = c.getDeclaredFields(); for(Field field : fields) { // 显示权限修饰,如public、protected、private System.out.print("\t" + Modifier.toString(field.getModifiers())); // 显示名称 System.out.print(" " + field.getType().getName() + " "); // 输出成员名称 System.out.println(field.getName() + ";"); }

  14. // 获得构造方法 Constructor[] constructors = c.getDeclaredConstructors(); for(Constructor constructor : constructors) { // 输出控制修饰public、protected、private System.out.print("\t" + Modifier.toString( constructor.getModifiers())); // 输出名称 System.out.println(" " + constructor.getName() + "();"); }

  15. // 获得成员函数 Method[] methods = c.getDeclaredMethods(); for(Method method : methods) { System.out.print("\t" + Modifier.toString( method.getModifiers())) System.out.print(" " + method.getReturnType().getName() + " "); System.out.println(method.getName() + "();"); }

  16. 动态生成对象 • 使用Class的newInstance()方法來实例化一个对象 Class c = Class.forName(args[0]); List list = (List) c.newInstance(); for(int i = 0; i < 5; i++) { list.add("element " + i); } for(Object o: list.toArray()) { System.out.println(o); }

  17. 如果要动态加载并生成对象,则须指定初始参数如果要动态加载并生成对象,则须指定初始参数 • 要先指定参数类型 • 取得构造方法 • 使用Constructor的newInstance()并指定参数后生成实例

  18. 动态生成对象 Class c = Class.forName(args[0]); // 指定参数类型 Class[] params = new Class[2]; // 第一个参数是String params[0] = String.class; // 第二个参数是int params[1] = Integer.TYPE; // 取得对应参数的构造方法 Constructor constructor = c.getConstructor(params); // 指定参数的值 Object[] argObjs = new Object[2]; argObjs[0] = "zhang"; argObjs[1] = new Integer(20); // 生成实例 Object obj = constructor.newInstance(argObjs);

  19. 小结 在java.lang.Object类中定义了getClass()方法,因此对于任意一个Java对象,都可以通过此方法获得对象的类型。Class类是Reflection API中的核心类,它有以下方法。 ◆getName():获得类的完整名字。◆getFields():获得类的public类型的属性。◆getDeclaredFields():获得类的所有属性。◆getMethods():获得类的public类型的方法。◆getDeclaredMethods():获得类的所有方法。◆getMethod(String name, Class[] parameterTypes):获得类的特定方法,name参数指定方法的名字,parameterTypes参数指定方法的参数类型。◆getConstrutors():获得类的public类型的构造方法。◆getConstrutor(Class[] parameterTypes):获得类的特定构造方法,parameterTypes参数指定构造方法的参数类型。◆newInstance():通过类的不带参数的构造方法创建这个类的一个对象。

  20. 执行方法 • 使用invoke()方法来动态执行指定的方法

  21. Class c = Class.forName(args[0]); // 使用无参数的构造方法建立对象 Object targetObj = c.newInstance(); // 指定参数类型 Class[] param1 = {String.class}; // 根据参数获得对应方法 Method setNameMethod = c.getMethod("setName", param1); // 设定参数值 Object[] argObjs1 = {"wang"}; // 运行方法 setNameMethod.invoke(targetObj, argObjs1); Class[] param2 = {Integer.TYPE}; Method setScoreMethod = c.getMethod("setScore", param2); Object[] argObjs2 = {new Integer(90)}; setScoreMethod.invoke(targetObj, argObjs2); System.out.println(targetObj);

  22. 私有方法的例子 Method privateMethod = c.getDeclaredMethod("somePrivateMethod", new Class[0]); privateMethod.setAccessible(true); privateMethod.invoke(targetObj, argObjs);

  23. 修改成员值 Class c = Class.forName(args[0]); Object targetObj = c.newInstance(); Field testInt = c.getField("testInt"); testInt.setInt(targetObj, 99); Field testString = c.getField("testString"); testString.set(targetObj, "caterpillar"); System.out.println(targetObj); Field privateField = c.getDeclaredField("privateField"); privateField.setAccessible(true); privateField.setInt(targetObj, 99);

  24. 例子

  25. 安全性和反射 • 在处理反射时安全性是一个较复杂的问题。反射经常由框架型代码使用,可能希望框架能够全面接入代码,无需考虑常规的接入限制。但是,不受控制的接入会带来严重的安全性风险。 • 由于这些互相矛盾的需求,Java编程语言定义一种多级别方法来处理反射的安全性。

More Related