java中的反射机制详解

  在Java运行时环境中,对于任意一个类,能否知道这个类有哪些属性和方法?对于任意一个对象,能否调用它的任意一个方法?答案是肯定的。这种动态获取类的信息,以及动态调用对象的方法的功能来自于Java语言的反射(Reflection)机制。Java反射机制主要提供了以下功能:

       1.在运行时判断任意一个对象所属的类;
       2.在运行时构造任意一个类的对象;(在编译时通过new()方法就可以构造一个类的对象)
       3.在运行时判断任意一个类所具有的成员变量和方法;
   4.在运行时调用任意一个对象的方法;
       5.生成动态代理。

  Reflection 是 Java 被视为动态(或准动态)语言的关键,允许程序于执行期利用Reflection APIs 取得任何已知名称之 class 的內部信息,包括 package、type、parameters、superclass、implemented interfaces、inner classes、 outer class、fields、constructors、methods、modifiers(如public,static等),并可于运行期生成instances、改变 fields 內容或调用methods(包括私有的方法,即通过反射我们可以打破类的包装机制)。

  一般而言,开发者社区说到动态语言,大致认同的一个定义是:“程序运行时,允许改变程序结构和变量类型,这种语言就称为动态语言。”从这个观点看,perl,python,ruby,javascript等是动态语言,c,c++,c#,java等都不是动态语言。

  尽管在这样的定义与分类下,java并不是动态语言,但他却有着一个非常突出的动态相关机制:Reflection。这个字的意思是“反射、映射、倒影”,用在java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes。换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或调用其methods。这种“看透 class”的能力(the ability of the program to examine itself)被称为introspection(内省、内观、反省)。Reflection和introspection是常被并提的两个术语。

  在JDK中,主要由以下类来实现Java反射机制,这些类都位于java.lang.reflect包中。

  •   Class类:代表一个类。(位于java.lang)
  •   Field类:代表类的成员变量(成员变量也称为类的属性)。
  •   Method类:代表类的方法。
  •   Constructor类:代表类的构造方法。
  •   Array类:提供了动态创建数组,以及访问数组元素的静态方法。
Field类:   提供有关类或接口的属性的信息,以及对它的动态访问权限。反射的字段可能是一个类(静态)属性或实例属性,简单的理解可以把它看成一个封装反射类的属性的类。
Constructor类: 提供关于类的单个构造方法的信息以及对它的访问权限。这个类和Field类不同,Field类封装了反射类的属性,而Constructor类则封装了反射类的构造方法。
Method类: 提供关于类或接口上单独某个方法的信息。所反映的方法可能是类方法或实例方法(包括抽象方法)。 这个类不难理解,它是用来封装反射类方法的一个类。
Class类: 类的实例表示正在运行的 Java 应用程序中的类和接口。枚举是一种类,注释是一种接口。每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。
Object类: 每个类都使用 Object 作为超类。所有对象(包括数组)都实现这个类的方法。

  在java中,无论生成某个类的多少个对象,这些对象都对应于同一个class对象。 


  要想使用反射,首先要获得对应类或对象的Class对象,获取某个类或对象的Class对象的三种方法:
  1. 使用Class类的静态方法:Class<?> classType = Class.forName("java.lang.String");
  2. 使用的.class语法:Class<?> classType = String.class;
  3. 适用对象的getClass()方法:String s = "aa"; Class<?> classType = s.getClass();

  若想通过反射来生成类的对象,有以下两种方式:
  1. 先生成欲生成对象对应的Class对象,然后通过Class对象的newInstance()方法直接生成新的实例对象:
      Class<?> classType = String.class;
      String str = classType.newInstance();
  2. 先生成欲生成对象对应的Class对象,然后通过Class对象的getConstructor()方法生成构造方法对象,再通过该构造方法对象来生成新的实例对象:
      Class<?> classType = String.class;
    Constructor<?> constructor = classType.getConstructor();
      String str = constructor.newInstance();  
  其中后者可以通过给getConstructor()方法传递参数而指定特定的构造方法(前者只能使用默认的即参数为空的构造方法):
    Class<?> classType = object.getClass();
    Constructor<?> constructor = classType.getConstructor(new Class[]{String.class, int.class});
    Object obj = constructor.newInstance(new Object[]{"tom", 23});

  

 1 import java.lang.reflect.Field;
 2 import java.lang.reflect.Method;
 3 
 4 
 5 public class ReflectTest {
 6     public Object copy (Object object) throws Exception{
 7         Class<?> classType = object.getClass();
 8         Object objectCopy = classType.getConstructor(new Class[]{})
 9             .newInstance(new Object[]{});
10         Field[] fields = classType.getDeclaredFields();
11         for(Field field: fields) {
12             String name = field.getName();
13             String firstLetter = name.substring(0, 1).toUpperCase();
14             String setMethodName = "set" + firstLetter + name.substring(1);
15             String getMethodName = "get" + firstLetter + name.substring(1);
16             Method setMethod = classType.getMethod(setMethodName, new Class[]{field.getType()});
17             Method getMethod = classType.getMethod(getMethodName, new Class[]{});
18             setMethod.invoke(objectCopy, new Object[]{getMethod.invoke(object, new Object[]{})});            
19         }
20         return objectCopy;
21     }    
22     
23     public static void main(String[] args) throws Exception{
24         Customer customer = new Customer("Tom", 23);
25         customer.setId(1L);
26         ReflectTest reflectTest = new ReflectTest();
27         Customer customer2 = (Customer)reflectTest.copy(customer);
28         System.out.println(customer2.getId() + "," + customer2.getName() + "," + customer2.getAge());
29     }
30 }
31 
32 class Customer {
33     private Long id;
34     private String name;
35     private int age;
36     
37     public Customer() {
38     }
39     
40     public Customer(String name, int age) {
41         this.name = name;
42         this.age = age;
43     }
44 
45     public Long getId() {
46         return id;
47     }
48 
49     public void setId(Long id) {
50         this.id = id;
51     }
52 
53     public String getName() {
54         return name;
55     }
56 
57     public void setName(String name) {
58         this.name = name;
59     }
60 
61     public int getAge() {
62         return age;
63     }
64 
65     public void setAge(int age) {
66         this.age = age;
67     }
68 }

  

 

  

 

 

 

posted @ 2012-11-20 12:59  beanmoon  阅读(310)  评论(0编辑  收藏  举报