javareflectionprivate-methods

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


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


Solution

  • If you want to invoke a non-static method you need to call it on instance of a class which has such method. In your case you want to call it on instance of private inner class MyInnerClass.

    But since you don't have any instance of such class yet you need to create it. Since Java can't let inner class object be created without outer class object, you will need to have such outer object too (instance of MyBigClass).

    So generally these are steps you need to take:

    You can do it like this:
    (just remember that default constructors of class have same visibility as visibility of that class. So private class will have private default constructor, so we will need to make it accessible before we can use it)

    try {
        //creating outer class object
        Object outer = new MyBigClass();
        
        //creating inner class object
        Class<?> innerClass = Class.forName("MyBigClass$MyInnerClass");
        Constructor<?> constructor = innerClass.getDeclaredConstructor(MyBigClass.class);//constructors of inner classes require as first parameter instance of its outer class
        constructor.setAccessible(true);//private inner class has private default constructor
        Object child = constructor.newInstance(outer);//created inner object must know which outer object is used to create it
    
        //TADA!!!
        //invoking method on inner class object
        Method method = innerClass.getDeclaredMethod("wantedMethod",new Class<?>[]{});
        method.setAccessible(true);//since method is private
        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