Is it possible to instantiate a private inner class from another class using Java reflection. For example if I took this code
public class Main {
public static void main(String[] args) {}
}
class OtherClass {
private class Test {}
}
is it possible to instantiate and gain access to Test from the main method in the class main.
Accessing the Private Members To instantiate the inner class, initially you have to instantiate the outer class. Thereafter, using the object of the outer class, following is the way in which you can instantiate the inner class.
Yes, you can instantiate a private inner class with Java reflection. To do that, you need to have an instance of outer class and invoke the inner class constructor which will use outer class instance in its first argument.
If we want to access Private Field and method using Reflection we just need to call setAccessible(true) on the field or method object which you want to access. Class. getDeclaredField(String fieldName) or Class. getDeclaredFields() can be used to get private fields.
You can access the private methods of a class using java reflection package.
Yes, you can instantiate a private inner class with Java reflection. To do that, you need to have an instance of outer class and invoke the inner class constructor which will use outer class instance in its first argument.
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");
}
}
}
When we don't know name of private inner class and we assume that it has no-argument constructor:
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);
}
}
Now we can make this code clearer if we have informations like
So instead of checking list of inner classes and picking first one, we can get selected inner class by its name using
Class<?> inner = Class.forName("our.pack.age.OuterClass$InnerClass")
// ^^^^^^^^^^^
Similarly we can select constructor we want to use by invoking getDeclaredConstructor(outerType,rest,of,parameter,types)
so if our inner class would look like
class OuterClass {
private class InnerClass {
private int x;
public InnerClass(int x) {
this.x = x;
System.out.println("inner object created");
}
}
}
our code could be
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"));
}
}
Output:
inner object created
42
When using reflection, you'll find constructors of that inner class taking an instance of the outer class as an additional argument (always the first) .
See these questions for related information:
Instantiating inner class
How can I instantiate a member class through reflection on Android
In Java, how do I access the outer class when I'm not in the inner class?
Example:
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<InnerClass> 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();
}
}
}
You can do the following :
public static void main(String[] args) throws Exception {
// to get first class in OtherClass
Class<?> innerClass = OtherClass.class.getDeclaredClasses()[0];
// getDeclaredConstructors for private constructor
Constructor<?> constructor = innerClass.getDeclaredConstructors()[0];
// to enable accessing private constructor
constructor.setAccessible(true);
OtherClass outerObject = new OtherClass();
//// create instance of Test by reflection
Object o = constructor.newInstance(outerObject);
System.out.println(o);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With