使用javareflection实例化私有内部类
是否可以使用Javareflection从另一个类实例化私有内部类。 例如,如果我使用此代码
public class Main { public static void main(String[] args) {} } class OtherClass { private class Test {} }
是否可以从类main中的main方法实例化并获得对Test的访问权限。
使用reflection时,您会发现该内部类的构造函数将外部类的实例作为附加参数(始终是第一个)。
有关相关信息,请参阅以下问题
-
实例化内部类
-
如何通过Android上的reflection实例化成员类
-
在Java中,当我不在内部类时,如何访问外部类?
例:
import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; public class OuterClass { private class InnerClass { } public OuterClass() { super(); } public static void main(String[] args) { // instantiate outer class OuterClass outer = new OuterClass(); // List all available constructors. // We must use the method getDeclaredConstructors() instead // of getConstructors() to get also private constructors. for (Constructor> ctor : OuterClass.InnerClass.class .getDeclaredConstructors()) { System.out.println(ctor); } try { // Try to get the constructor with the expected signature. Constructor ctor = OuterClass.InnerClass.class .getDeclaredConstructor(OuterClass.class); // This forces the security manager to allow a call ctor.setAccessible(true); // the call try { OuterClass.InnerClass inner = ctor.newInstance(outer); System.out.println(inner); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } } catch (NoSuchMethodException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
是的,您可以使用Javareflection实例化私有内部类。 要做到这一点,你需要有一个外部类的实例并调用内部类构造函数,它将在其第一个参数中使用外部类实例。
class OuterClass { private class InnerClass { { //this block is just to confirm that the inner object was created //it will be added to every constructor of this class System.out.println("inner object created"); } } }
当我们不知道私有内部类的名称时,我们假设它没有参数构造函数:
class Main { //no comment version public static Object giveMeInnerInstance() throws Exception{ OuterClass outerObject = new OuterClass(); Class> innerClass = OuterClass.class.getDeclaredClasses()[0]; Constructor> constructor = innerClass.getDeclaredConstructors()[0]; constructor.setAccessible(true); return constructor.newInstance(outerObject); } //commented version public static void main(String[] args) throws Exception { //we need an outer class object to use the inner object constructor //(the inner class object needs to know about its parent object) OuterClass outerObject = new OuterClass(); //let's get the inner class //(we know that the outer class has only one inner class, so we can use index 0) Class> innerClass = OuterClass.class.getDeclaredClasses()[0]; //or if we know name of inner class we can use //Class> innerClass = Class.forName("full.package.name.OuterClass$InnerClass") //since constructor so we could use it to pass instance of outer class and change //its accessibility. We can use this code to get default constructor of InnerClass //since we know that this is the only constructor here Constructor> constructor = innerClass.getDeclaredConstructors()[0]; //we could also use //Constructor> constructor = innerClass.getDeclaredConstructor(OuterClass.class); //the default constructor of the private class has same visibility that class has //so it is also private, so to be able to use it we need to make it accessible constructor.setAccessible(true); //now we are ready to create inner class instance Object innerObject = constructor.newInstance(outerObject); } }
现在,如果我们有类似的信息,我们可以使这个代码更清晰
- 内在的名字,
- 构造函数参数
因此,我们可以使用名称来选择内部类,而不是检查内部类列表并选择第一个内部类
Class> inner = Class.forName("our.pack.age.OuterClass$InnerClass") // ^^^^^^^^^^^
类似地,我们可以通过调用getDeclaredConstructor(outerType,rest,of,parameter,types)
来选择我们想要使用的构造getDeclaredConstructor(outerType,rest,of,parameter,types)
这样如果我们的内部类看起来像
class OuterClass { private class InnerClass { private int x; public InnerClass(int x) { this.x = x; System.out.println("inner object created"); } } }
我们的代码可能是
class ReflectionDemo { //no comment version public static Object giveMeInnerInstance() throws Exception{ OuterClass outerObject = new OuterClass(); Class> innerClass = Class.forName("com.stackoverflow.q14112166.OuterClass$InnerClass"); Constructor> constructor = innerClass.getDeclaredConstructor(OuterClass.class, int.class); constructor.setAccessible(true); return constructor.newInstance(outerObject,42); } public static Object getFieldValue(Object obj, String fieldName) throws Exception{ Class> clazz = obj.getClass(); Field field = clazz.getDeclaredField(fieldName); field.setAccessible(true); return field.get(obj); } //lets test our code public static void main(String[] args) throws Exception { Object innerClassObject = giveMeInnerInstance(); System.out.println(getFieldValue(innerClassObject, "x")); } }
输出:
inner object created 42