一、創建對象
通過反射創建對象有兩種方式:
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參數就是幾維數組,三維數組的元素是二維數組,二維數組的元素是一維數組。
五、其他的操作不再一一演示,用的時候查閱文檔即可