轉自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;
}