Java反射获取内部类有局限

这周接触到继承及修改具有包访问权的内部类内容,略梳理了下各种资料,发觉在包外修改内部类内容必须通过实例.......

网上关于这部分的内容比较少,参考了下这位的帖子:http://blog.csdn.net/helloapps/article/details/5716604

反射里的Class, Field, Method, Constructor都是S物,必须结合对象使用,除非是静态的。

获取非public对象须用类似getDeclaredMethod()而不是getMethod()。

Field和Method都能设置accessible(true),之后能访问到私有权限。

这里贴的两个类,放在不同包里,能通过内部类实例修改其成员,也能使用内部类构造函数新建实例....但是还不清楚能否进一步到能修改内部类函数里的变量?

Outer class and inner class:

package ee.test1;

public class OuterClass {

    private Inner2 inn2 = new Inner2();
    
    public static final int PUBLIC_STATIC_NUMBER = 100;
    static int DEFAULT_STATIC_NUMBER = 200;
    public int PUBLIC_NUMBER = 300;
    protected int PROTECTED_NUMBER = 400;
    private int PRIVATE_NUMBER = 500;
    
    private String str[] = {"Str1", "Str2", "Str3"};

    public Runnable ta = new Runnable() {
        public void run() {
            System.out.println("Method in anonymous class is executed!");
        }
    };

    private class Inner2 {
        String ta2;

        public Inner2() {
            ta2 = "A";
            System.out.println("Inner2 is instantiated!");
        }

        public void p2() {
            System.out.println("ta2: " + ta2);
        }
    }

    class Inner3 {
        public Inner3() {
            System.out.println("Inner2 is instantiated!");
        }
    }

    public class Inner1 {
        public Inner1() {
            System.out.println("Inner1 is instantiated!");
        }
    }
}

Test:

package ff.test2;

import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

import ee.test1.OuterClass;

public class ReflectInnerTest {

    public static void main(String args[]) {
        OuterClass ric = new OuterClass();
        try {
            reflectInner(ric);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void reflectInner(OuterClass ric)
            throws InstantiationException, IllegalAccessException,
            SecurityException, NoSuchMethodException, IllegalArgumentException,
            InvocationTargetException, ClassNotFoundException,
            NoSuchFieldException {
        Class<? extends OuterClass> clazz = ric.getClass();

        // anonymous class has NO constructor, cannot create instant or access
        // method
        // but could access the method and member as follows:
        Runnable r = (Runnable) (clazz.getField("ta").get(ric));
        r.run();

        // Below to access inner class via its member.
        Field f2 = clazz.getDeclaredField("inn2");
        f2.setAccessible(true);
        Class<?> cls = f2.getType();
        Field f3 = cls.getDeclaredField("ta2");
        f3.setAccessible(true);
        Method m2 = cls.getDeclaredMethod("p2", null);
        m2.setAccessible(true);
        // f2.get(ric) (== ric.inn2) is to get the inn2 instant(which is Outer's
        // member)
        m2.invoke(f2.get(ric), null); // get original value
        f3.set(f2.get(ric), "C"); // change it at run-time
        m2.invoke(f2.get(ric), null); // show the value again

        Field field1 = clazz.getDeclaredField("PUBLIC_STATIC_NUMBER");
        field1.setAccessible(true);
        System.out.println(field1.getInt(null));

        Field field2 = clazz.getDeclaredField("DEFAULT_STATIC_NUMBER");
        field2.setAccessible(true);
        System.out.println(field2.getInt(null));

        Field field3 = clazz.getDeclaredField("PUBLIC_NUMBER");
        field3.setAccessible(true);
        System.out.println(field3.getInt(ric));

        Field field4 = clazz.getDeclaredField("PROTECTED_NUMBER");
        field4.setAccessible(true);
        System.out.println(field4.getInt(ric));

        Field field5 = clazz.getDeclaredField("PRIVATE_NUMBER");
        field5.setAccessible(true);
        System.out.println(field5.getInt(ric));

        Field field6 = clazz.getDeclaredField("str");
        field6.setAccessible(true);
        System.out.println(((String[]) field6.get(ric))[0]);
        System.out.println(Array.get(field6.get(ric), 1));

        // ----------------------------------------
        // Below gets the array of inner classes
        Class<?> classes[] = clazz.getDeclaredClasses();
        for (Class<?> c : classes) {// Reflect on member classes
            int i = c.getModifiers();
            String s = Modifier.toString(i);
            if (s.contains("static"))// handle static inner class
                c.getConstructor().newInstance();
            else {
                // instantiate inner classes
                Constructor cons = c.getDeclaredConstructor(ric.getClass());
                cons.setAccessible(true);
                Object c1 = cons.newInstance(ric);
                if (c.getSimpleName().equals("Inner2")) {
                    Method m = c.getDeclaredMethod("p2", null);
                    m.setAccessible(true);
                    m.invoke(c1, null);
                    Field f = c.getDeclaredField("ta2");
                    f.setAccessible(true);
                    f.set(c1, "B");
                    m.invoke(c1, null);
                }
            }
        }
        // -------------------------------------------------
    }
}
原文地址:https://www.cnblogs.com/lionfight/p/3650295.html