java核心學習(三十九) 通過反射生成並操作對象


一、創建對象

  通過反射創建對象有兩種方式:

    1、 使用Class對象的newInstance()方法,這種方法實際上是使用默認的構造器起來創建該類的實例

    2、使用Class對象獲取指定的Constructor對象,調用Constructor對象的newInstance()方法來獲取來創建該Class的實例,這樣可以根據參數類型來指定使用哪個構造器。

  下面代碼實現一個簡單工廠類,該工廠類可以根據配置文件產生Object類的子類

  

public class ObjectFactory {
    private static String propertiesFileName;
    private static Map<String, Object> objectPool;

    public static String getPropertiesFileName() {
        return propertiesFileName;
    }

    public static void setPropertiesFileName(String propertiesFileName) {
        ObjectFactory.propertiesFileName = propertiesFileName;
    }

    public static Object getObject(String key) {
        if (objectPool.isEmpty()) {
            try (
                    FileInputStream fis = new FileInputStream(propertiesFileName)
            ) {
                Properties props = new Properties();
                props.load(fis);
                for (String name : props.stringPropertyNames()) {
                    objectPool.put(name,CreatObject(props.getProperty(name)));
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return objectPool.get(key);
    }
    public static Object CreatObject(String className)throws ClassNotFoundException,IllegalAccessException,InstantiationException{
        Class clazz = Class.forName(className);
        return clazz.newInstance();
    }
}

二、調用方法

  由Class對象可以獲得該Class的Method對象,調用Method對象的invoke()方法可以調用該Method,下面為該方法簽名:

      

   返回值Object即為執行方法后的返回值,第一個參數obj指定由哪個對象來執行該方法,后面的args參數代表執行該方法傳入的參數。在調用invoke方法是要注意訪問修飾符的權限。使用isAccessible方法來判斷,使用setAccessible方法來判斷權限。

  如果調用的方法為靜態方法,則第一個參數為null。

   下面代碼對上面的對象工廠加強,允許在配置文件中增加配置對象的的成員變量的值,對象工廠會讀取配置並利用對象的setter方法設置成員變量的值。

   由於這個例子用作實驗反射調用方法,所以另外實現了一個簡單工廠類,而沒有使用工廠模式將工廠類抽象出來便於拓展。

  

public class ExtendObjectFactory {
    private static String propertiesFileName;
    private static Map<String, Object> objectPool;

    public static String getPropertiesFileName() {
        return propertiesFileName;
    }

    public static void setPropertiesFileName(String propertiesFileName) {
        ExtendObjectFactory.propertiesFileName = propertiesFileName;
    }
    public static Object CreatObject(String className)throws ClassNotFoundException,IllegalAccessException,InstantiationException{
        Class clazz = Class.forName(className);
        return clazz.newInstance();
    }
    public static Object getObject(String key){
        if (objectPool.isEmpty()) {
            try (
                    FileInputStream fis = new FileInputStream(propertiesFileName)
            ) {
                Properties props = new Properties();
                props.load(fis);
                for (String name : props.stringPropertyNames()) {
//                    objectPool.put(name,CreatObject(props.getProperty(name)));
                    //取出每一對key-value對,如果key中包含百分號,則認為該key用於控制對象的setter方法設置值,%前半為對象名字,后半控制setter方法名
                    if(name.contains("%")){
                        String[] objAndProp = name.split("%");
                        Object target = objectPool.get(objAndProp[0]);
                        String methodName = "set" + objAndProp[1].substring(0,1).toUpperCase()+objAndProp[1].substring(1);
                        Class targetClass = target.getClass();
                        Method setterMethod = targetClass.getMethod(methodName,String.class);
                        setterMethod.invoke(target,props.getProperty(name));
                    }else {
                        objectPool.put(name,CreatObject(props.getProperty(name)));
                    }

                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return objectPool.get(key);
    }
}

  配置文件的格式可以如同這般

1 a=javax.swing.JFrame
2 b=javax.swing.JLabel
3 #set the title of a
4 a%title=Test Title

 

 

三、訪問成員變量的值

  Field類提供了如下兩組方法:

    getXxx(Object obj) :獲取obj對象的的該成員變量的值,此處的Xxx指8種基本類型,若成員變量的類型為引用類型,則取消后面的Xxx。

    setXxx(Object obj,Xxx val) 類似於上面的方法。

四、操作數組

  java.lang.reflect包下還提供了一個Array類,Array對象可以代表所有的數組,程序可以使用Array來動態創建數組,操作數組。

  Array類提供的方法簽名:

  

  length參數是可變個數參數,有幾個length參數就是幾維數組,三維數組的元素是二維數組,二維數組的元素是一維數組。

五、其他的操作不再一一演示,用的時候查閱文檔即可


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM