mosawi mosawi - 1 year ago 280
Java Question

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, one will use
v1.jar
and the other will use
v2.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();

app1.run();
app2.run();
}


Here are EngineV1 and V2 with Interface:

public Interface IEngine {
void 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 void run() {
// some logic...
}
}

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 void run() {
// some logic...
}
}


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?

Answer Source

When you declare a no arg 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");      
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download