2

I defined a public no-argument constructor inside an inner class, and my code keeps throwing a NoSuchMethoException when I call getConstructor().

I'm calling the problem method within the outer class using:

addListeners( info_boxes, InfoBoxListener.class.getName() );

My inner class:

public class InfoBoxListener implements View.OnClickListener
{
    public InfoBoxListener()
    {
        //Why isn't this constructor being found?
    }

    @Override
    public void onClick(View view) 
    {
        //some code         
    }
}

The method throwing the exception:

private void addListeners( List<View> views, String class_name )
{   
        try 
        {
            Class<?> clazz = Class.forName( class_name );

            Constructor<?> ctor = clazz.getConstructor(); //EXCEPTION

            for ( View view : views )
            {
                Object object = ctor.newInstance();
                view.setOnClickListener( (View.OnClickListener) object );
            }

        } 
        catch (ClassNotFoundException e) 
        {
            Log.i("mine",  "class not found: " + e.getMessage() );
        }
        catch (NoSuchMethodException e) 
        {
            Log.i("mine",  "method not found: " + e.getMessage() );
        }
        catch (Exception e) 
        {
        }
}

My google-fu has failed me. What in the world am I doing wrong?

Kacy
  • 3,330
  • 4
  • 29
  • 57
  • 1
    http://stackoverflow.com/questions/17485297/how-to-instantiate-inner-class-with-reflection-in-java – Reimeus Aug 30 '15 at 22:59

2 Answers2

8

In Java, you can't call the constructor of the inner class without passing the outer class as parameter, do it like this:

Class<?> outerClass = Class.forName("myOuterClassName");
Object outerInstance = outerClass.newInstance();

Class<?> innerClass = Class.forName("myInnerClassName");
Constructor<?> ctor = innerClass.getDeclaredConstructor(outerClass);

Object innerInstance = ctor.newInstance(outerInstance);
GingerHead
  • 8,130
  • 15
  • 59
  • 93
  • 1
    I stumbled on this post just before you replied and one of the answers mentions the inner class having to be static: http://stackoverflow.com/questions/11446635/no-such-method-exception-hadoop-init I like your answer though because it allows me to leave my inner class non-static. – Kacy Aug 30 '15 at 23:03
  • 3
    You could eliminate the need to name the outer class, since you're already naming it when naming the inner class: `Class> outerClass = innerClass.getEnclosingClass()`. – Andreas Aug 30 '15 at 23:07
  • yeah you could do that as well – GingerHead Aug 30 '15 at 23:08
2

Your inner class is not static, so it needs a reference to an instance of the outer class. This is done by adding a hidden parameter to the constructor, but with reflection, it's not hidden.

To see this, create a small test program:

public class Test {
    public class InfoBoxListener
    {
        public InfoBoxListener()
        {
        }
    }
    public static void main(String[] args) {
        for (Constructor<?> constructor : InfoBoxListener.class.getConstructors()) {
            System.out.println(constructor);
        }
    }
}

Output

public Test$InfoBoxListener(Test)

As you can see, the constructor takes a Test parameter.

Andreas
  • 154,647
  • 11
  • 152
  • 247