Java筆記-反射機制(二)

上一篇文章介紹了反射的基本概念以及獲取類相關信息的反射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,展示反射在其中的運用。

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