反射机制

 Java反射是Java语言的一个很重要的特征,它使得Java具有了“动态性”。

   一般而言,开发者社群说到动态语言,大致认同的一个定义 是:“程序运行时,允许改变程序结构或者变量类型,这种语言称为动态语言”。从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C#不是动态语言。
   Reflection是java被视为动态(或准动态)语言的一个关键性质。
 
Java反射机制主要提供了一下功能:
   1、在运行时判断任意一个对象所属的类。
   2、在运行时构造任意一个类的对象。
   3、在运行时判断任意一个类所具有的成员变量和方法。
   4、在运行时调用任意一个对象的方法。
 
在JDK中,主要由一下类来实现Java反射机制,这些类都位于java.lang.reflect包中:
   1、Class类:代表一个类
   2、Field类:代表类的成员变量(成员变量也称为类的属性)
   3、Method类:代表类的方法
   4、Constructor类:代表类的构造方法。
   5、Array类:提供了动态创建数组,以及访问数组的元素的静态方法。
 
一、通过Class类获取成员变量、成员方法、接口,超类,构造方法等。
在java.lang.Object类中定义了getClass()方法,因此对于任意一个Java对象,都可以通过此方法获得对象的类型。Class类是ReflectionAPI中核心的类,它有以下方法
getName():获得类的完整名字
getFields():获得类的public类型的属性
getDeclaredFields():获得类的所有属性
getMethods():获得类的public类型的方法
getDeclaredMethods():获得类的所有方法
getMethod(String name,Class[] parameterTypes):获得类的特定方法,name参数指定方法的名字,parameterType参数指定方法的参数类型。
getConstructors():获得类的public类型的构造方法。
getConstructor(Class[] parameterTypes):获得类的特定构造方法,parameterType参数指定构造方法的参数类型
newInstance():通过类的不带参数的构造方法创建这个类的一个对象。
 
二、运行时复制对象
 
 1 package reflection;
 2 import java.lang.reflect.Field;
 3 import java.lang.reflect.Method;
 4 public class ReflectTester {
 5     public Object copy(Object object) throws Exception {
 6         // 获得对象的类型
 7         Class<?> classType = object.getClass();
 8         System.out.println("Class:" + classType.getName());
 9         // 通过默认构造方法创建一个新的对象
10         System.out.println("该类的构造方法有:"+classType.getConstructors()[0]);
11         Object objectCopy = classType.getConstructor()
12                 .newInstance();
13         // 获得对象的所有属性
14         Field[] fields = classType.getDeclaredFields();
15         for (int i = 0; i < fields.length; i++) {
16             Field field = fields[i];
17             String fieldName = field.getName();
18             System.out.println("fieldName:"+fieldName);
19             String firstLetter = fieldName.substring(0, 1).toUpperCase();
20             // 获得和属性对应的getXXX()方法的名字
21             String getMethodName = "get" + firstLetter + fieldName.substring(1);
22             // 获得和属性对应的setXXX()方法的名字
23             String setMethodName = "set" + firstLetter + fieldName.substring(1);
24             // 获得和属性对应的getXXX()方法
25             Method getMethod = classType.getMethod(getMethodName,
26                     new Class[] {});
27             // 获得和属性对应的setXXX()方法
28             Method setMethod = classType.getMethod(setMethodName,
29                     new Class[] { field.getType() });
30             // 调用原对象的getXXX()方法
31             Object value = getMethod.invoke(object);
32             System.out.println(fieldName + ":" + value);
33             // 调用拷贝对象的setXXX()方法
34             setMethod.invoke(objectCopy, new Object[] { value });
35         }
36         return objectCopy;
37     }
38     public static void main(String[] a) throws Exception {
39         Customer customer = new Customer("Tom", 21);
40         customer.setId(new Long(1));
41         Customer customerCopy = (Customer) new ReflectTester().copy(customer);
42         System.out.println(customerCopy==customer);
43         System.out.println(customerCopy.equals(customer));
44         System.out.println("Copy information:" + customerCopy.getId() + ""
45                 + customerCopy.getName() + "" + customerCopy.getAge());
46     }
47 }
48 class Customer {
49     private Long id;
50     private String name;
51     private int age;
52     public Customer() {
53     }
54     public Customer(String name, int age) {
55         this.name = name;
56         this.age = age;
57     }
58     public Long getId() {
59         return id;
60     }
61     public String getName() {
62         return name;
63     }
64     public int getAge() {
65         return age;
66     }
67     public void setId(Long id) {
68         this.id = id;
69     }
70     public void setName(String name) {
71         this.name = name;
72     }
73     public void setAge(int age) {
74         this.age = age;
75     }
76 }                                                                          
解说:ReflectTester类的copy(object,object)方法依次执行以下步骤
(1)获得对象的类型
  Class classType=object.getClass();
  System.out.println("Class:"+classType.getName());
(2)通过默认构造方法创建一个新对象:
 Object objectCopy=classType.getConstructor().newInstance();
以上代码先调用Class类的getConstructor()方法获得一个Constructor对象,它代表默认的构造方法,然后调用Constructor对象的newInstance()方法构造一个实例。
(3)获得对象的所有属性:
    Field[] fields=classType.getDeclaredFields();
    Class类的getDeclaredFields()方法返回类的所有属性。
(4)获得每个属性对应的getXXX()和setXXX()然后执行这些方法,把原来的属性拷贝到新的对象中。
 
三、用反射机制调用对象的方法
 1 package reflection;
 2 import java.lang.reflect.InvocationTargetException;
 3 import java.lang.reflect.Method;
 4 public class InvokeTester {
 5   public int add(int param1,int param2){
 6       return param1+param2;
 7   }
 8   
 9   public String echo(String msg){
10       return "echo:"+msg;
11   }
12   
13   public static void main(String[] args) throws InstantiationException, IllegalAccessException, SecurityException, NoSuchMethodException, IllegalArgumentException, InvocationTargetException{
14       Class<?> classType=InvokeTester.class;
15       Object invokeTester =classType.newInstance();
16       
17       //获取InvokeTester类的add()方法
18       Method addMethod=classType.getMethod("add", int.class,int.class);
19       //调用invokeTester对象上的add()方法
20       Object result=addMethod.invoke(invokeTester,100,200);
21       System.out.println((Integer)result);
22       
23       //获取InvokeTester类的echo方法
24       Method echoMethod=classType.getMethod("echo", java.lang.String.class);
25       
26     Object echoResult=echoMethod.invoke(invokeTester, "HelloWorld");
27     System.out.println(echoResult);
28       
29   }
30 }

 

四、动态创建和访问数组
 
创建简单的一维数组
 1 import java.lang.reflect.Array;
 2 public class ArrayTester1 {
 3     public static void main(String[] args) throws ClassNotFoundException {
 4         Class<?> classType=Class.forName("java.lang.String");
 5         //创建一个长度为10的字符串数组
 6         Object array=Array.newInstance(classType, 10);
 7         //把索引位置为5的元素设为“hello”
 8         Array.set(array, 5, "hello");
 9         //获得索引位置为5的元素的值
10         String s=(String)Array.get(array, 5);
11         System.out.println(s);
12     }
13 }

创建多维数组

 1 public class ArrayTester2 {
 2     /**
 3      * @param args
 4      */
 5     public static void main(String[] args) {
 6         
 7       //创建一个int类型的3维数组,维度分别是5,10,15
 8       Object array=Array.newInstance(int.class, 5,10,15);
 9       Object arrayObj=Array.get(array, 3);
10       Class<?> cls=arrayObj.getClass().getComponentType();
11       System.out.println(array.getClass().getComponentType());
12       System.out.println(cls);
13       
14       arrayObj=Array.get(arrayObj, 5);
15       Array.setInt(arrayObj, 10, 37);
16       int[][][] arrarCast=(int[][][]) array;
17       System.out.println(arrarCast[3][5][10]);
18     }
19 }

 

posted @ 2016-10-31 13:51  久眠深巷  阅读(82)  评论(0)    收藏  举报