问题
I have compiled a class at runtime which I would like to use on the fly, provided that its constructor takes one parameter
package com.notmycompany;
import com.mycompany.Manager;
import com.mycompany.Processor;
import com.mycompany.Event;
public class CustomProcessor extends Processor {
public CustomProcessor( Manager m) {
super( m);
}
@Override
public void process( Event evt) {
// Do you own stuff
System.out.println( "My Own Stuff");
}
}
Compilation goes fine and I can load the class right away. But the constructor is giving me a hard time.
Class<?> clazz = urlClassLoader.loadClass("com.notmycompany.CustomProcessor");
Constructor<?> constructor = clazz.getConstructor( com.mycompany.Manager.class);
this.customProcessor = (Processor) constructor.newInstance( this.manager);
In this case, getConstructor
throws a NoSuchMethodException
I tried using getConstructors
instead, which only gets me one step further with IllegalArgumentException
during newInstance
call (of course this.manager is com.mycompany.Manager)
Constructor<?> list[] = clazz.getConstructors();
Constructor<?> constructor = list[0];
this.customProcessor = (Processor) constructor.newInstance( this.manager);
Watever I do, there is a mismatch between Manager object at runtime and compilation
How can I fix this constructor signature?
Edit 1: getParameterTypes output
for( Class<?> c : constructor.getParameterTypes()) {
System.out.println( c);
}
outputs
class com.mycompany.Manager
Edit 2: I removed constructor parameter as a temporary workaround
Now the code throws ClassCastException
complaining that com.notmycompany.CustomProcessor cannot be cast to com.mycompany.Processor
when constructor is invoked:
Constructor<?> constructor = clazz.getConstructor();
this.customProcessor = (Processor) constructor.newInstance();
This all seems to be part of the same problem where runtime classes seem inconsistent with compilation's, although names match.
回答1:
Your CustomProcessor class has no constructor because the name of the method you believe to be your constructor is different.
public CustomLatencyProcessor(Manager m) {
super(m);
}
Should be changed to
public CustomProcessor(Manager m) {
super(m);
}
Because the name of your class is CustomProcessor. Constructor's names must match the name of their containing class exactly.
回答2:
I have been able to get it to work eventually after using a URL that uses the currentThread as parent (as opposed to a URLClassLoader created from scratch with URLs)
URLClassLoader ucl = (URLClassLoader)Thread.currentThread().getContextClassLoader();
URLClassLoader ucl2 = new URLClassLoader( new URL[] { new URL( "file://d:/temp/")},ucl);
Class<?> clazz = ucl2.loadClass("com.notmycompany.CustomProcessor");
I hope this can save you 2 days!
来源:https://stackoverflow.com/questions/17517275/reflection-type-mismatch