Java反射获取内部类的实例

Java反射获取内部类的实例

在java中,反射机制能在运行状态中获取任意一个类的所有属性和方法,并可以对该类的某个对象获取其属性的值或执行某个方法。虽然使用反射会降低程序的性能,增加项目复杂度,但是适当的时候使用反射可以使代码更加灵活,如动态代理。
这里重点记录下如何通过反射构造出内部类的实例。内部类分为成员内部类,局部内部类,静态内部类,匿名内部类,这里不考虑局部内部类情况了。
考虑如下类,需要通过反射创建其中三个内部类,匿名内部类是一个属性的值。这里三个内部类的访问权限都是private的。

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");
        }
    };

}  

构造获取三个内部类的方法:

@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

总结

1、由于成员内部类对象的创建依赖于外部类对象,持有指向外部类对象的引用。所以在反射构造成员内部类的时候一定要通过获取构造器再调用构造器的newInstance方法,其中必须要传入外部类的Class和实例。对于私有构造器,需要使用getDeclaredConstructor方法获取并使用setAccessible(true)来设置为可以获取的。

2、静态内部类不持有外部类的引用,所以当其提供了无参显式的构造器的时候,可以直接在调用其class的newInstance()方法获得实例。如果构造器为private的则处理同1中。如果没有提供显式的的无参构造器,只提供了有参构造器,处理也同1中。

3、如果内部类没有提供显式的构造器,则通过上面提到的方法构造内部类对象会抛出java.lang.IllegalAccessException错误。即要通过上面提到的方法使用反射机制创建内部类对象,内部类一定要提供显式的构造函数!

以上结论纯为个人结合文中给出的代码测试得出,有分析错误或不全面的地方还望指出!谢谢~

参考

java反射技术详解(对内部类的处理)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值