java反射机制

所以我们就不用麻烦了。如果我们拿到一个类的类型信息,就可以利用反射获取其各种成员以及方法了。(注:Class 从JDK1.5版本后就开始更多为泛型服务了)那么我们怎么拿到一个类型的信息呢?假设我们有一个Role类:

 

package yui;

 

 /**

  * A base class having some attributes and methods

  * @author Octobershiner

  * @since 2012 3 17

  * 

  * */

 public class Role 

     private String name;

     private String type;  

     // Constructors

     public Role(){

         System.out.println("Constructor Role() is invoking");

     }

     //私有构造器

     private Role(String name){

         this.name = name;

         System.out.println("Constructor Role(String name) is invoking.");

     }

     //get and set method

     public String getName() {

         return name;

     }

     public void setName(String name) {

         this.name = name;

     }

     public String getType() {

         return type;

     }

     public void setType(String type) {

         this.type = type;

     }

     //override the toString method to show the class

     @Override

     public String toString(){

         return "This is a role called " this.name;

     }

 }

 

在没有对象实例的时候,主要有两种办法。       
 //获得类类型的两种方式
Class cls1 = Role.class;
Class cls2 = Class.forName("yui.Role");
注意第二种方式中,forName中的参数一定是完整的类名(包名 类名),并且这个方法需要捕获异常。现在得到cls1就可以创建一个Role类的实例了,利用Class的newInstance方法相当于调用类的默认的构造器
          Object o = cls1.newInstance(); //创建一个实例
//Object o1 = new Role(); //与上面的方法等价
这样就创建了一个对象,缺点是我们只能利用默认构造函数,因为Class的newInstance是不接受参数的,后面会讲到可接受参数的newInstance,第二,如果类的构造函数是private的,比如Class,我们仍旧不能实例化其对象 

  获取类的构造器                                                                                                                                                        

  首先介绍一下Constructor类,这个类用来封装反射得到的构造器,Class有四个方法来获得Constructor对象

  • public Constructor<?>[] getConstructors()      返回类中所有的public构造器集合,默认构造器的下标为0
  • public Constructor<T> getConstructor(Class<?>... parameterTypes)   返回指定public构造器,参数为构造器参数类型集合
  • public Constructor<?>[] getDeclaredConstructors()  返回类中所有的构造器,包括私有
  • public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 返回任意指定的构造器
    从名字来看,还是很好懂的,带上Declared的都是获得所有的构造方法,包括私有,哈,这下我们就可以调用原本不允许调用的私有构造器了,看代码
 /**
2 * 获取构造方法Constructor
3 * getConstructor() only for public
4 * getDeclaredConstructor() global access all
5 *
6 * */
7
8 //指定参数列表获取特定的方法
9 Constructor con = cls1.getDeclaredConstructor(new Class[]{String.class});
10 con.setAccessible(true); //设置可访问的权限
11 Object obj = con.newInstance(new Object[]{"liyang"});
12 System.out.println(obj); //打印一下这个对象的信息
13
14         //获取所有的构造方法集合
15         Constructor con1[] = cls1.getDeclaredConstructors();
16 con1[1].setAccessible(true);
17 Object obj1 = con1[1].newInstance(new Object[]{"tom"});
18 System.out.println(obj1);

        了解了构造器,其实你可以猜到成员变量的获取方法了,成员变量用Field类进行封装。
       主要的方法非常的类似:
  • public Field getDeclaredField(String name)  获取任意指定名字的成员
  • public Field[] getDeclaredFields()             获取所有的成员变量
  • public Field getField(String name)           获取任意public成员变量
  • public Field[] getFields()                          获取所有的public成员变量
    可以看出这些方法都是异曲同工的,好了直接看一下例子吧
/**
          * 获取成员变量Field
          * getField()
          * getDeclaredField()
          * */
         Field mem = cls1.getDeclaredField("name");
         mem.setAccessible(true);      
         System.out.println("we get form field :" mem.get(obj));
  获取类的方法                                                                                                                                                               
   我觉得你已经可以帮我写这一段了,封装类的方法的类是Method.获取method也有四个方法,猜到了没??
  • public Method[] getMethods()    获取所有的共有方法的集合
  • public Method getMethod(String name,Class<?>... parameterTypes) 获取指定公有方法 参数1:方法名 参数2:参数类型集合  
  • public Method[] getDeclaredMethods()  获取所有的方法
  • public Method getDeclaredMethod(String name,Class<?>... parameterTypes) 获取任意指定方法
       看下面的例子吧
        /**
          * 调用类的方法 Method
          * getMethod()
          * getDeclaredMethod()
          * 
          * */
         Method f = cls1.getMethod("getName", null);
         Object name = f.invoke(obj, null);
         System.out.println("we invoke method : " name);
这个很简单吧,无参的时候我们只要传null就行了
实例:

package org.curry.tool; import java.lang.reflect.Method;

public class InvokeMethods {

public static void main(String[] args) {  
 Employee emp = new Employee();   
 Class cl = emp.getClass();
//是Class,而不是class  
// /getClass获得emp对象所属的类型的对象,Class就是类的类             
// /Class是专门用来描述类的类,比如描述某个类有那些字段,             
// /方法,构造器等等!   
try {    
// /getMethod方法第一个参数指定一个需要调用的方法名称   
 // /这里是Employee类的setAge方法,第二个参数是需要调用     
// 方法的参数类型列表,是参数类型!如无参数可以指定null     
// /该方法返回一个方法对象    
 Method sAge = cl.getMethod("setAge", new Class[] { int.class });
//参数必须和方法中一样int和Integer,double和Double被视为不同的类型   
 Method gAge = cl.getMethod("getAge", null);   
 Method pName = cl.getMethod("printName",      new Class[] { String.class });        
Object[] args1 = { new Integer(25) };    
// 参数列表    
// emp为隐式参数该方法不是静态方法必须指定    
sAge.invoke(emp, args1);    
Integer AGE = (Integer) gAge.invoke(emp, null);    
int age = AGE.intValue();    
System.out.println("The Employee Age is: " age);    
Object[] args3 = { new String("Jack") };    pName.invoke(emp, args3);   
} catch (Exception e) {    e.printStackTrace();   }   System.exit(0);  } }

class Employee {  
// 定义一个员工类    
public Employee() {   
age = 0;   name = null;  
}  
// 将要被调用的方法    
public void setAge(int a) {   
age = a;  
}  
// 将要被调用的方法    
public int getAge() {   
return age;  
}  
// 将要被调用的方法  
public void printName(String n) {   
name = n;   
System.out.println("The Employee Name is: " name);  
}  
private int age;  
private String name;
}

posted on 2013-05-21 15:42  明天521  阅读(82)  评论(0编辑  收藏  举报