I want to test a private method that existe inside a private inner class
public class MyBigClass {
private class MyInnerClass {
private void wantedMethod() {
}
}
}
I want to call the wantedMethod()
to test it
Here is my code
Class[] classes = MyBigClass.class.getDeclaredClasses();
for (int i = 0; i < classes.length; i++) {
// this code print "MyInnerClass"
System.out.println(">> inner classes >> " + classes[i].getSimpleName());
if (classes[i].getSimpleName().equals("MyInnerClass")) {
Class clazz = classes[i];
// Constructor c=clazz.getConstructor();
Method[] methods = clazz.getDeclaredMethods();
// this code print "wantedMethod"
for (int j = 0; j < methods.length; j++) {
System.out.println("inner class methods >> " + methods[i].getName());
}
}
}
Problem : I cannot call wantedMethod()
If you want to invoke a non-static method you need to tell on which object you want to invoke it. In your case you want inner class object, but since you don't have one yet you need to create it. Since Java can't let inner class object be created without outer class object you will need to create that outer object too.
So these are steps you need to take:
You can do it like this:
(you just need to remember that default constructors have same visibility as visibility of its class, so private class will have private constructor which we will need to make accessible before we will be able to use it)
try {
//creating parent object
Object outer = new MyBigClass();
//creating inner class object
Class<?> innerClass = Class.forName("MyBigClass$MyInnerClass");
Constructor<?> constructor = innerClass.getDeclaredConstructor(MyBigClass.class);//inner object must know type of outer class
constructor.setAccessible(true);//private inner class has private default constructor
Object child = constructor.newInstance(outer);//inner object must know about its outer object
//invoking method on inner class object
Method method = innerClass.getDeclaredMethod("wantedMethod",new Class<?>[]{});
method.setAccessible(true);//in case of unaccessible method
method.invoke(child,new Object[]{});
} catch (ClassNotFoundException | NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
You can find more info about creating inner class object via reflection in this question
This is because your class isn't named CodeCircuit
. Remove that if
condition and it will work.
Also remove the line Constructor c=clazz.getConstructor();
as it throws an exception.
After making these changes, your own code prints
>> inner classes >> MyInnerClass
inner class methods >> wantedMethod
Use this code to execute the method.
Class<?>[] classes = MyBigClass.class.getDeclaredClasses();
for (Class<?> clazz : classes) {
if(clazz.getSimpleName().equals("MyInnerClass")) {
Method method = clazz.getDeclaredMethod("wantedMethod", new Class[] {});
method.setAccessible(true);
method.invoke(clazz.getDeclaredConstructor(MyBigClass.class).newInstance(new MyBigClass()), new Object[] {});
}
}
The syntax is a bit strange, making you to use the outer class for getting hold of the inner class constructor. It behaves as if you have a constructor with the below signature defined in your inner class:
public MyInnerClass(MyBigClass bigClass) {
}
But, I assume that's how Java handles inner (nested) classes using reflection.
Note that you'll have to provide a public
constructor for your inner class.
public class MyBigClass {
private class MyInnerClass {
public MyInnerClass() {
System.out.println("hello");
}
private void wantedMethod() {
System.out.println("world");
}
}
}
You'll also have to setAccessible(true)
on the private method in order to be able to invoke it.
Upon further investigation, when I decompiled the generated MyBigClass$MyInnerClass.class
class, I found that my hunch was right:
public class MyBigClass$MyInnerClass {
public MyBigClass$MyInnerClass(MyBigClass paramMyBigClass) {
System.out.println("hello");
}
private void wantedMethod() {
System.out.println("world");
}
}
Would be really glad if someone can throw some light into this behaviour
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