在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錯誤。 即要經過上面提到的方法使用反射機制建立內部類對象,內部類必定要提供顯式的構造函數!