Java反射獲取內部類的實例

Java中,反射機制能在運行狀態中獲取任意一個類的全部屬性和方法,並能夠對該類的某個對象獲取其屬性的值或執行某個方法。雖然使用反射會下降程序的性能,增長項目複雜度,可是適當的時候使用反射可使代碼更加靈活,如動態代理。 
這裏重點記錄下如何經過反射構造出內部類的實例。內部類分爲成員內部類,局部內部類,靜態內部類,匿名內部類,這裏不考慮局部內部類狀況了。 java

考慮以下類,須要經過反射建立其中三個內部類,匿名內部類是一個屬性的值。這裏三個內部類的訪問權限都是private的。apache

public class InnerContainer {   

    public InnerContainer() { }

    private class InnerA {
        private String f = InnerA.class.getSimpleName();
        public InnerA() { }
    }

    private static class InnerB {
        private String f = InnerB.class.getSimpleName();
        public InnerB() {}
    }

    private Runnable r = new Runnable() {       
        @Override
        public void run() {
            System.out.println("Method run of Runnable r");
        }
    };

}

構造獲取三個內部類的方法:ide

@SuppressWarnings({ "rawtypes", "unchecked" })
    public static void main(String[] args) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchFieldException {
        Class clazz = InnerContainer.class;
        InnerContainer container = (InnerContainer) clazz.newInstance();
        Class innerClazz[] = clazz.getDeclaredClasses();
        for (Class cls : innerClazz) {
            int mod = cls.getModifiers();
            String modifier = Modifier.toString(mod);
            if (modifier.contains("static")) {
                //構造靜態內部類實例
//              Constructor con1 = cls.getDeclaredConstructor();
                Object obj1 = cls.newInstance();
                Field field1 = cls.getDeclaredField("f");
                field1.setAccessible(true);
                System.out.println(field1.get(obj1));
            } else {
                // 構形成員內部類實例
                Constructor con2 = cls.getDeclaredConstructor(clazz);
                con2.setAccessible(true);
                Object obj2 = con2.newInstance(container);
                Field field2 = cls.getDeclaredField("f");
                field2.setAccessible(true);
                System.out.println(field2.get(obj2));
            }
        }
        // 獲取匿名內部類實例
        Field field = clazz.getDeclaredField("r");
        field.setAccessible(true);
        Runnable r = (Runnable) field.get(container);
        r.run();
    }

輸出 函數

InnerA
InnerB
Method run of Runnable r

總結

一、因爲成員內部類對象的建立依賴於外部類對象,持有指向外部類對象的引用。因此在反射構形成員內部類的時候必定要經過獲取
   構造器再調用構造器的newInstance方法,其中必需要傳入外部類的Class和實例。對於私有構造器,須要使用
   getDeclaredConstructor方法獲取並使用setAccessible(true)來設置爲能夠獲取的。

二、靜態內部類不持有外部類的引用,因此當其提供了無參顯式的構造器的時候,能夠直接在調用其class的newInstance()方法得到
   實例。若是構造器爲private的則處理同1中。若是沒有提供顯式的的無參構造器,只提供了有參構造器,處理也同1中。

三、若是內部類沒有提供顯式的構造器,則經過上面提到的方法構造內部類對象會拋出java.lang.IllegalAccessException錯誤。
   即要經過上面提到的方法使用反射機制建立內部類對象,內部類必定要提供顯式的構造函數!
相關文章
相關標籤/搜索