上一篇文章介紹了反射的基本概念以及獲取類相關資訊的反射API,這一章節主要記錄如何對類的成員進行操作的相關反射API。
操作類成員的類
反射API中提供瞭如下介面,用於對類的成員進行操作。
java.lang.reflect.Member
複製程式碼
該介面主要有以下三個實現類,用於對類成員中的欄位,方法和構造器進行操作。
Tips: 在Java SE 7的手冊中指出,構造器不是類的成員,這和Member的實現類想表達的意思不同。
操作欄位
欄位擁有型別以及值,使用以下類能夠獲取類中欄位的型別資訊,獲取欄位的值以及對欄位進行賦值操作。
java.lang.reflect.Field
複製程式碼
操作方法
方法有返回值,引數,並且可能會丟擲異常,使用以下類可以獲取方法引數以及返回值的型別資訊,也可以呼叫指定物件的方法。
java.lang.reflect.Method
複製程式碼
操作構造器
使用如下類可以操作類的構造器,提供與操作method類似的方法,但有以下兩點例外,構造器沒有有返回值,並且對構造器的呼叫可以建立指定類的例項。
java.lang.reflect.Constructor
複製程式碼
實際操作
獲取欄位型別
public class Main {
public static String abc = "123";
private static List<String> a;
public static void main(String[] args) throws NoSuchFieldException {
Class c = Main.class;
Field field = c.getField("abc");
Field field1 = c.getDeclaredField("a");
System.out.println(field.getType());
System.out.println(field.getGenericType());
System.out.println();
System.out.println(field1.getType());
System.out.println(field1.getGenericType());
}
}
複製程式碼
如上程式碼所示,獲取對應欄位的Field類,具體使用區別在上一張文末介紹了。 getType直接輸出這個欄位的類型別。 getGenericType直接輸出這個欄位的型別,如果是泛型欄位的話,輸出帶有泛型實際引數的型別,如果不是泛型則會在內部呼叫getType。結果如下所示。
class java.lang.String
class java.lang.String
interface java.util.List
java.util.List<java.lang.String>
複製程式碼
獲取欄位修飾符
類中欄位有許多的修飾符,比如 public,private,transient等,java提供了API獲取類的修飾符,不過獲取出來的是一個int型數字,好在java提供了Modifier類對獲得的整型進行判斷,如下程式碼所示,有興趣的可以對Modifier原始碼進行瀏覽。
public class Main {
public static int a = 1;
public static void main(String[] args) throws NoSuchFieldException {
Class c = Main.class;
Field field = c.getField("a");
System.out.println(Modifier.isPublic(field.getModifiers()));
System.out.println(Modifier.isStatic(field.getModifiers()));
}
}
複製程式碼
讀寫欄位值
反射可以對欄位進行讀寫,如下程式碼所示,可以用過setX和getX方法對欄位進行讀寫,不過要注意讀寫前後的型別是否匹配,不然會報異常。
private static int a = 1;
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
Class c = Main.class;
Field field = c.getDeclaredField("a");
int b = field.getInt(Main.class);
System.out.println(b);
field.setInt(Main.class, 2);
System.out.println(a);
field.setFloat(Main.class, (float) 1.1); // 報異常
}
複製程式碼
操作方法和構造器
之後操作方法的類是Method,操作構造器的類是Constructor,通過這些API提供的get方法,可以獲得方法和構造器的相關資訊,因此在筆記裡也不再贅述。
構造器建立例項
構造器和方法的反射類不同點在於,Constructor可以建立例項,程式碼如下所示。
public class Main {
public Main() {
}
public static void main(String[] args) throws IllegalAccessException, InvocationTargetException, InstantiationException {
Class c = Main.class;
Constructor[] ctors = c.getConstructors();
Constructor ctor = null;
for (int i = 0; i < ctors.length; i++) {
ctor = ctors[i];
if (ctor.getGenericParameterTypes().length == 0) // 需要找到預設建構函式建立例項
break;
}
System.out.println(ctor.newInstance().getClass().getCanonicalName());
}
}
複製程式碼
結尾
以上就是一些看反射API的一些記錄,這個工具本身使用上還是很簡單的,但意義還是比較大的,是很多框架存在的基礎,下一篇以struts為例子,寫一個小demo,展示反射在其中的運用。