是的,您可以使用 Java 反射实例化私有内部类。为此,您需要有一个外部类的实例并调用内部类构造函数,该构造函数将在其第一个参数中使用外部类实例。
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)
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