Java 反射内部类相关问题解析

阿里云幸运券

问:如下代码段,已获取外部类实例情况下如何反射实例化内部类及调用内部类方法?

class OuterClass {
    public void func(){
        System.out.println("Outer class.");
    }
    class InnerClass {
        private String mName;
        public InnerClass(String name) {
            mName = name;
        }
        void getName(){
            System.out.println("name is:"+mName);
        }
    }
}

答:本题贵在考察反射内部类的注意事项,实质就是在考察对于内部类的理解,内部类不了解的可以查看本号历史推送中内部类面试专题。下面直接给出答案完整代码,如下。

class OuterClass {
    public void func() {
        System.out.println("Outer class.");
    }
    class InnerClass {
        private String mName;
        public InnerClass(String name) {
            mName = name;
        }
        void getName() {
            System.out.println("name is:"+mName);
        }
    }
}
public class Demo {
    public static void main(String[] args) throws Exception {
        Class outerClass = Class.forName("OuterClass");
        //通过外部类的方法名获取外部类的方法
        Method method = outerClass.getDeclaredMethod("func");
        //调用外部类实例的func方法,invoke第一参数为外部类实例
        method.invoke(outerClass.newInstance());
        //内部类反射名字需要使用$分隔,编译后生成的规则
        Class innerClass = Class.forName("OuterClass$InnerClass");
        //通过内部类的方法名获取内部类的方法
        Method method2 = innerClass.getDeclaredMethod("getName");
        //特别注意!!!!内部类newInstance的第一个参数必须是外部类实例的引用
        method2.invoke(innerClass.getDeclaredConstructors()[0].newInstance(outerClass.newInstance(),"yan"));
    }
}

即便上面 InnerClass 的修饰符是 private,上面的代码依旧可以成功反射,只是不能直接通过 outClass.new InnerClass(“yan”); 的方式去实例化内部类。

同理当上面 InnerClass 的修饰符如果是 static,即内部类是静态内部类时上面的代码就不能用了,需要将答案的最后一行代码改成 method2.invoke(innerClass.getDeclaredConstructors()[0].newInstance(“yan”)); 才行,因为静态内部类没有持有外部类的任何引用,所以不用传递外部类实例对象的引用。

问:如何反射如下类的匿名内部成员类?

class OuterClass {
    public Runnable runnable = new Runnable() {
        public void run() {
            System.out.println("runnable.");
        }
    };
}

答:其实这种场景你就不要把它想成匿名内部类了,直接当作外部类的成员变量去反射即可,如下。

class OuterClass {
    public Runnable runnable = new Runnable() {
        public void run() {
            System.out.println("runnable.");
        }
    };
}
public class Demo {
    public static void main(String[] args) throws Exception {
        Class outerClass = Class.forName("OuterClass");
        Runnable runnable = (Runnable) (outerClass.getField("runnable").get(outerClass.newInstance()));
        runnable.run();
    }
}

所以说,想要灵活运用反射,用好反射就必须先熟练掌握 Java 各种核心基础知识,譬如变长参数、内部类实质原理等等,不然在写反射代码时会觉得很懵逼。

腾讯云代金券

原文链接

https://mp.weixin.qq.com/s?__biz=MzI3ODc3NzQ4NQ%3D%3D&mid=2247484508&idx=1&sn=79945bd4ae90771719d219c5326e98db&chksm=eb509fbedc2716a89f7332ff322fe92d43eb91d1972a40193cd3ed03eab6f081ffe659cbc5ab&mpshare=1&scene=23&srcid=0428Wt6Vn4P6hDeJcW7d0PRx%23rd

服务推荐

猜你喜欢

转载自blog.csdn.net/weixin_44476888/article/details/89521008
今日推荐