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错误。
   即要经过上面提到的方法使用反射机制建立内部类对象,内部类必定要提供显式的构造函数!
相关文章
相关标签/搜索