这周接触到继承及修改具有包访问权的内部类内容,略梳理了下各种资料,发觉在包外修改内部类内容必须通过实例.......
网上关于这部分的内容比较少,参考了下这位的帖子: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); } } } // ------------------------------------------------- } }