How to call a private method that exists inside a private inner class

josephino picture josephino · May 16, 2012 · Viewed 7.1k times · Source

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()

Answer

Pshemo picture Pshemo · May 16, 2012

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:

  • create outer class object (if you don't have one),
  • using outer class object create inner class object,
  • invoke method on inner class object.

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