我有一个java源代码,将在运行时编译。我正在编译源代码(作为字符串呈现)并将其加载到一个类中,如下所示:
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
compiler.run(null, null, null, sourceFile.getPath());
// Load and instantiate compiled class.
URLClassLoader classLoader = URLClassLoader.newInstance(new URL[] { root.toURI().toURL() });
Class<?> cls = Class.forName("TakeAdvantageOftMapComponents", true, classLoader);
这个类包含一个方法,我需要将其命名为runJob
。通常我会这样做:
TakeAdvantageOftMapComponents c = new TakeAdvantageOftMapComponents();
c.runJob(new string[]);
现在我在运行时编译的类中出现了相同的方法。但是我怎么称呼它呢?
比起使用反射来调用你想要的方法,你可能想要声明一个interface
来扩展你的类,例如:
package ccjmne;
public interface JobRunner {
public void runJob(final String[] args);
}
…并使你的类实现 interface
:
文件:/home/eric/stackoverflow/A.java
package stackoverflow;
public class A implements ccjmne.JobRunner {
public void runJob(final String args[]) {
for(final String str : args) {
System.out.println(str);
}
}
}
最后,按如下方式加载这个类:
final Class<JobRunner> cls = (Class<JobRunner>) Class.forName("stackoverflow.A", true, classLoader);
注意,我知道我这里有一个JobRunner
。
因此,我可以简单地做:
cls.newInstance().runJob("Hello world!".split(" "));
…这样就完成了!
示例工作代码:
package ccjmne;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;
public class JobRunnerTest {
public static void main(final String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, MalformedURLException {
final JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
final File root = new File("/home/eric/");
compiler.run(null, null, null, root + "/stackoverflow/A.java");
final URLClassLoader classLoader = URLClassLoader.newInstance(new URL[] { root.toURI().toURL() });
final Class<JobRunner> cls = (Class<JobRunner>) Class.forName("stackoverflow.A", true, classLoader);
cls.newInstance().runJob("Hello world!".split(" "));
}
}
输出:Hello
world!