简体   繁体   中英

java.lang.NoSuchMethodException Java

I'm trying to call 2 different versions of the same dependency library ( jars ) within a top level Main class . So I created an interface with 2 implementation classes, both classes have a run method which makes use of common apis one will use somejar-1.0.0-SNAPSHOT.jar and the other will use somejar-2.0.0-SNAPSHOT.jar by explicitly calling ClassLoader.

public static void main(String[] args) throws MalformedURLException, ClassNotFoundException, InstantiationException, IllegalAccessException {

    ClassLoader loader1 = new URLClassLoader( new URL[] { new File("/Users/haddad/.m2/repository/com/company/somejar-1.0.0-SNAPSHOT.jar").toURL() });
    ClassLoader loader2 = new URLClassLoader( new URL[] { new File("/Users/haddad/.m2/repository/com/company/somejar-2.0.0-SNAPSHOT.jar").toURL() });

    Class<?> c1 = loader1.loadClass("com.engine.na.EngineV1");
    Class<?> c2 = loader2.loadClass("com.engine.na.EngineV2");

    IEngine app1 = (IEngine) c1.newInstance();
    IEngine app2 = (IEngine) c2.newInstance();

    Integer s1 = app1.run();
    Integer s2 = app2.run();
    Assert.equals(s1,s2,"Outputs from somejar-1.0 and somejar-2.0 did not match, perhaps somejar-2.0 has regressed?");
}

Here are EngineV1 and V2 with Interface:

public Interface IEngine {
    Integer run();
}

public class EngineV1 implements IEngine {
    private File content;
    private File en;
    public EngineV1(args) {
       this.content = new File("/some/path");
       this.en = new File("/some/path");
    }
    public static void main(String[] args) {
        new EngineV1(args).run();
    }

    public Integer run() {
        // some logic...
        somejar.evaluateSpeed();
    }
}

public class EngineV2 implements IEngine {
    private File content;
    private File en;
    public EngineV2(args) {
       this.content = new File("/some/path");
       this.en = new File("/some/path");
    }
    public static void main(String[] args) {
        new EngineV2(args).run();
    }

    public Integer run() {
        // some logic...
        somejar.evaluateSpeed();
    }
}

When I go to run the main class I get:

Exception in thread "main" java.lang.InstantiationException: com.engine.na.EngineV1
    at java.lang.Class.newInstance(Class.java:427)
    at com.engine.na.MainClass.main(MainClass.java:23)
Caused by: java.lang.NoSuchMethodException: com.engine.na.EngineV1.<init>()
    at java.lang.Class.getConstructor0(Class.java:3082)
    at java.lang.Class.newInstance(Class.java:412)
    ... 1 more

Why do I get this error? How to solve for this?

When you declare a constructor in a class, the default constructor with no argument is not generated at compile time.

You have two ways :

  • adding explicitly a constructor with no argument.

  • invoking by reflection the constructor with an argument.

The first way is the easy trick and is a very generic way but it not necessarily the best way if it matters to value the state or one of part of the instance when it is created.

For this first case, it is self explanatory.
For the second case, the idea is you have to retrieve the constructor with argument from the class and specify the argument when you use it.

For example with this constructor :

public EngineV1(String value) {
      ...
}

You can invoke it in this way :

Class<EngineV1> c1 = (Class<EngineV1>)loader1.loadClass("com.engine.na.EngineV1");
Constructor<EngineV1> constructor = c1.getConstructor(String.class);
EngineV1 instance = ctor.newInstance("myString");      

If there are no constructor defined in class then only compiler will create a no-arg constructor for your class.

But as in your case you are defining a parameterized constructor and in that case you need to provide a no-arg constructor for Reflection to create instances by calling it.

Or you can check available constructors for your class by calling getConstructor() method and then call newInstance() on that.

Follow below link for more information : http://docs.oracle.com/javase/tutorial/reflect/member/ctorInstance.html

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM