我有一个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[]);
现在,我在运行时编译的类中存在同样的方法。但我怎么称呼它?
答案 0 :(得分:1)
优于使用反射来调用您想要的方法,您可能希望声明您的类会扩展的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!