java反射——實現程序的動態性

轉自http://uuhorse.iteye.com/blog/1706466

① 創建對象
    如果知道一個類型,很容易使用new操作符創建一個類的實例。但是如果在編譯時並不知道具體要實例化的是哪個類的對象,如何創建該實例呢?
    Java中提供Class.forName(String className)從一個字符串(含包的類全名稱)加載一個類,再利用newInstance方法創建該類的實例。 

//動態創建類對象  
public static Object createObject(String className) {  
    Object object = null;  
    try {  
        Class classDefinition = Class.forName(className);  
        object = classDefinition.newInstance();  
    } catch (InstantiationException e) {  
        System.out.println(e);  
    } catch (IllegalAccessException e) {  
        System.out.println(e);  
    } catch (ClassNotFoundException e) {  
        System.out.println(e);  
    }  
    return object;  
}

當然,也可以先獲取一個類的Constructor,再調用其newInstance方法創建對象。不同的是,constructor對象的newInstance方法需要傳遞一個對象數組作爲構造方法的參數列表。

//使用Constructor動態創建對象  
public static Object createObject(Constructor constructor, Object[] arguments) {  
    System.out.println("Constructor: " + constructor.toString());  
    Object object = null;  
    try {  
        object = constructor.newInstance(arguments);  
        System.out.println("Object: " + object.toString());  
        return object;  
    } catch (InstantiationException e) {  
        System.out.println(e);  
    } catch (IllegalAccessException e) {  
        System.out.println(e);  
    } catch (IllegalArgumentException e) {  
        System.out.println(e);  
    } catch (InvocationTargetException e) {  
        System.out.println(e);  
    }  
    return object;  
} 
② 獲取/設置字段值
    利用Reflection API獲取或者設置字段的值,首先要得到Class對象,然後利用Class對象的getField方法取得相應的字段Field對象,然後調用Field對象對應的getXXX/setXXX方法獲取或者設置屬性的值。Filed對象提供getInt/setInt、getLong/setLong等方法對基本類型的屬性進行值的獲取和設置,可以直接使用get/set方法獲取複雜類型屬性的值(返回一個對象值/傳遞一個對象值作爲參數)。
    具體操作方法見如下代碼片段。當然,若試圖獲取/設置一個非public的字段值(getField方法也不能獲取非pubic的屬性對象,可以嘗試使用getDeclaredField方法),將產生IllegalAccessException,可以通過setAccessible(true)使非public的字段可見,然後對字段值進行訪問。

        // 獲取字段值  
        static void getFiledValue(Object o, String filedName) {  
            Class c = o.getClass();  
            Field filed;  
            Object value;  
            try {  
                filed = c.getField(filedName);  
    //          filed = c.getDeclaredField(filedName);  
    //          filed.setAccessible(true);  //修改字段訪問權限  
                value = filed.get(o);   //可使用getInt、getLong等(若知曉字段基本類型)  
                System.out.println(filedName + ": " + value.toString());  
            } catch (NoSuchFieldException e) {  
                System.out.println(e);  
            } catch (SecurityException e) {  
                System.out.println(e);  
            } catch (IllegalAccessException e) {  
                System.out.println(e);  
            }  
        }  

 // 修改字段值  
    public static void setFieldValue(Object o, String filedName, Object value) {  
        Field filed;  
        Class c = o.getClass();  
        try {  
            filed = c.getField(filedName);  
//          filed = c.getDeclaredField(filedName);  
//          filed.setAccessible(true);  //修改字段訪問權限  
            filed.set(o, value);    //可使用setInt、setLong等(若知曉字段基本類型)  
        } catch (NoSuchFieldException e) {  
            System.out.println(e);  
        } catch (IllegalAccessException e) {  
            System.out.println(e);  
        }  
    }  


③ 調用方法
    方法調用的過程類似於設置字段值的過程,首先要得到Class對象,然後調用getMethod方法得到方法Method的對象,getMethod方法要求傳遞兩個參數,一個是方法名,第二個是Class[],即方法參數列表中各參數對應的類型的數組。然後執行Method對象的invoke方法,進行方法的調用,invoke方法需要傳遞兩個參數,第一個是方法綁定的對象,第二個是方法的參數列表。如果是static的方法,則第一個參數將自動被忽略(可爲null)。
    同理,對於非public的方法,可以使用getDeclaredMethod方法獲取Method對象,並使用setAccessible設置其可見性。 

   //動態調用方法  
    public static Object callMethod(Object o, String methodName,  
            Class paramsType[], Object paramsValue[]) {  
        Object result = null;  
        Class c;  
        Method method;  
        try {  
            c = o.getClass();  
            method = c.getMethod(methodName, paramsType);  
//          method = c.getDeclaredMethod(methodName, paramsType);  
//          method.setAccessible(true);  
            result = method.invoke(o, paramsValue);  
        } catch (NoSuchMethodException e) {  
            System.out.println(e);  
        } catch (IllegalAccessException e) {  
            System.out.println(e);  
        } catch (InvocationTargetException e) {  
            System.out.println(e);  
        }  
        return result;  
    }  




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章