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 反射内部类)