Cyril Deba
Cyril Deba

Reputation: 1210

java.lang.NoSuchMethodException and the parameterized constructor

I have a class Foo as follows:

public class Foo extends Bar
{
    public Foo(com.example.X displayState, com.example.Y parent)
    {
        super(displayState, parent);
    }
}

The Bar class is shown below:

public abstract class Bar {

    public Bar(com.example.X displayState, com.example.Y parent)
    {
        // do something with received params
    }
}

Additionally, there is a factory class with the following method:

 public static Object getInstance(Class theSourceClass, Class theTargetClass, Class[] parameterClasses, Object[] parameterValues)
 {
     Class theClass = (theTargetClass == null) ? theSourceClass : theTargetClass;

     try
     {
         Constructor classConstructor = theClass.getConstructor(parameterClasses);
         return classConstructor.newInstance(parameterValues);
     }
     catch (NoSuchMethodException exp)
     {
         // log
     }

The problem is that the NoSuchMethodException exception always arises:

java.lang.NoSuchMethodException: com.example.Foo.<init>(com.example.X, com.example.Y)
at java.lang.Class.getConstructor0(Class.java:2715) 
at java.lang.Class.getConstructor(Class.java:1659)
at com.example.MyFactory.getInstance(MyFactory.java:30)

I have debugged the code and the class information has correct details about the defined constructor; however, the exception is here.

Does anybody have any idea what is missed? Thanks!

Upvotes: 1

Views: 1449

Answers (2)

Cyril Deba
Cyril Deba

Reputation: 1210

The root of the problem was the different version of the compiled Bar, X, Y, and factory classes which were used for the compilation and in runtime. Let me explain.

All 4 guys (Bar, X, Y, and factory class) are compiled and come from the library file for the Foo class compilation. However, the production system always re-compile these classes.

I created the library, connected it to the build path, and forgot about it. Technically, the project has no errors during the compilation yet the reflection fails.

The solution was simple - remove the library and use re-generated Bar, X, Y, and factory classes for the Foo compilation.

Upvotes: 0

Kevin Bowersox
Kevin Bowersox

Reputation: 94479

The following example will produce an instance of Foo. The example ensures that a constructor in Bar exists that accepts X and Y.

Foo.java

public class Foo extends Bar {
    public Foo(com.example.X displayState, com.example.Y parent) {
        super(displayState, parent);
    }
}

Bar.java

import com.example.X;
import com.example.Y;


public class Bar {

    public Bar(X displayState, Y parent) {
        // TODO Auto-generated constructor stub
    }

}

X.java

package com.example;

public class X {

}

Y.java

 package com.example;

public class Y {

}

Test.java

import java.lang.reflect.Constructor;

import com.example.X;
import com.example.Y;

public class Test {
    public static void main(String[] args) {
        Class[] classes = {X.class, Y.class};
        Object[] values = {new X(), new Y()};

        Object obj = getInstance(Foo.class, null, classes, values);

        System.out.println(obj);
    }

    public static Object getInstance(Class theSourceClass,
            Class theTargetClass, Class[] parameterClasses,
            Object[] parameterValues) {
        Class theClass = (theTargetClass == null) ? theSourceClass
                : theTargetClass;

        try {
            Constructor classConstructor = theClass
                    .getConstructor(parameterClasses);
            return classConstructor.newInstance(parameterValues);
        } catch (Exception e) {

        }
        return null;
    }
}

Upvotes: 2

Related Questions