1. 程式人生 > >使用java反射操作類的建構函式,成員變數和成員方法

使用java反射操作類的建構函式,成員變數和成員方法

在java.lang.reflect包中有三個類Field,Method,Constructor.分別描述域,方法,構造器。參考API,關於這三個類的說明。

在執行時使用反射分析物件,如果訪問的是私有域或是私有方法,私有建構函式,會丟擲IllegalAccessException.因為反射機制的預設行為受限於java的訪問控制,然而,如果一個java程式沒有受到安全管理器的控制,就可以覆蓋訪問控制。為了達到這個目的,需要呼叫Field,Method,Constructor物件的setAccessible方法,setAccessible方法是AccessibleObject類的一個方法,是Field,Method,Constructor類的公共超類。

setAccessible(true);

不要過多地使用反射:破壞類封裝;效率偏低;編譯器不容易幫助發現錯誤,在執行時才會被發現。

我使用反射,是為了寫單元測試程式碼,對執行物件的分析,改變物件的私有域等,達到測試需要的覆蓋率。

以下提供程式碼事例:

測試類:

publicclass RunBing {
    
private String name;
    
privateint age;
    
public String sex;

    
public RunBing() {

    }


    
private RunBing(String name) {
        
this
.name = name;
    }


    
publicvoid setName(String name) {
        
this.name = name;
    }


    
publicvoid setAge(int age) {
        
this.age = age;
    }


    
public String getName() {
        
return name;
    }


    
publicint getAge() {
        
return age;
    }


    
public String run() {
        
return
"run method";
    }


    
private String add() {
        
return"add method";
    }

}

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Constructor;


publicclass ReflectHelp {

        
/**
         * 通過構造器取得例項
         * 
@param className 類的全限定名
         * 
@param intArgsClass 建構函式的引數型別
         * 
@param intArgs 建構函式的引數值
         * 
         * 
@return Object 
         
*/

        
publicstatic Object getObjectByConstructor(String className,Class[] intArgsClass,Object[] intArgs){

        Object returnObj
=null;
        
try{
            Class classType 
= Class.forName(className);
            Constructor constructor 
= classType.getDeclaredConstructor(intArgsClass); //找到指定的構造方法
            constructor.setAccessible(true);//設定安全檢查,訪問私有建構函式必須
            returnObj = constructor.newInstance(intArgs);
        }
catch (NoSuchMethodException ex) {
            ex.printStackTrace();
        }
catch (Exception ex) {
            ex.printStackTrace();
        }

        
return returnObj;
    }

    
/**
     * 修改成員變數的值
     * 
@param Object 修改物件
     * 
@param filedName 指定成員變數名
     * 
@param filedValue 修改的值
     *
     * 
@return 
     
*/

    
publicstaticvoid modifyFileValue(Object object, String filedName,
                                       String filedValue) 
{
        Class classType 
= object.getClass();
        Field fild 
=null;
        
try{
            fild 
= classType.getDeclaredField(filedName);
            fild.setAccessible(
true);//設定安全檢查,訪問私有成員變數必須
            fild.set(object, filedValue);
        }
catch (NoSuchFieldException ex) {
            ex.printStackTrace();
        }
catch (Exception ex) {
            ex.printStackTrace();
        }

    }


    
/**
     * 訪問類成員變數
     * 
@param Object 訪問物件
     * 
@param filedName 指定成員變數名
     * 
@return Object 取得的成員變數的值
     * 
*/

    
publicstatic Object getFileValue(Object object, String filedName) {
        Class classType 
= object.getClass();
        Field fild 
=null;
        Object fildValue 
=null;
        
try{
            fild 
= classType.getDeclaredField(filedName);
            fild.setAccessible(
true);//設定安全檢查,訪問私有成員變數必須
            fildValue = fild.get(object);

        }
catch (NoSuchFieldException ex) {
            ex.printStackTrace();
        }
catch (Exception ex) {
            ex.printStackTrace();
        }

        
return fildValue;
    }


    
/**
     * 呼叫類的方法,包括私有
     * 
@param Object 訪問物件
     * 
@param methodName 指定成員變數名
     * 
@param type 方法引數型別
     * 
@param value 方法引數指
     * 
@return Object 方法的返回結果物件
     * 
*/

    
publicstatic Object useMethod(Object object, String methodName,
                                   Class[] type, Class[] value) 
{
        Class classType 
= object.getClass();
        Method method 
=null;
        Object fildValue 
=null;
        
try{
            method 
= classType.getDeclaredMethod(methodName, type);
            method.setAccessible(
true);//設定安全檢查,訪問私有成員方法必須
            fildValue = method.invoke(object, value);

        }
catch (NoSuchMethodException ex) {
            ex.printStackTrace();
        }
catch (Exception ex) {
            ex.printStackTrace();
        }

        
return fildValue;
    }



    
publicstaticvoid main(String[] args) {
        RunBing runbing 
=new RunBing();
        runbing.setName(
"aaa");

        
//訪問成員變數
        String value = (String) ReflectHelp.getFileValue(runbing, "sex");
        System.out.println(
"value:"+ value);
        
//修改成員變數
        ReflectHelp.modifyFileValue(runbing, "sex""bbb");
        System.out.println(
"value:"+ runbing.getName());
        
//檢查修改後的變數值
        value = (String) ReflectHelp.getFileValue(runbing, "sex");
        System.out.println(
"value:"+ value);

        
//呼叫方法
        value = (String) ReflectHelp.useMethod(runbing, "add"new Class[] {},
                                               
new Class[] {});
        System.out.println(
"value:"+ value);

        
//使用指定建構函式
        Class[] inArgs =new Class[]{String.class};
        Object[] inArgsParms 
=new Object[]{"hanj"};
        RunBing runBing2 
= (RunBing)ReflectHelp.getObjectByConstructor("com.ccit.hj.reflect.RunBing",inArgs,inArgsParms);
        value 
= (String) ReflectHelp.getFileValue(runBing2, "name");
        System.out.println(
"cc -- value:"+ value);
    }