• 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);
                    }
                }
            }
            // -------------------------------------------------
        }
    }
  • 相关阅读:
    js分页--存储数据并进行分页
    纯CSS多级菜单
    ini文件操作
    XML文件数据操作
    身份证号码验证
    将DataSet(DataTable)转换成JSON格式(生成JS文件存储)
    将JSON(List集合)转成DataSet(DataTable)
    js打印(控件)及多种方式
    了解切面编程思想
    20190429版本-测试过程回溯
  • 原文地址:https://www.cnblogs.com/lionfight/p/3650295.html
Copyright © 2020-2023  润新知