使用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