在Java的动态编译中用到了两个Java底层类,即com.sun.tools.javac.Main和Class。
用过javascript的人都知道在JS中的eval()方法特别好用,可以动态的调用函数,但是在java中我们要实现类似的功能,实现动态编译该如何实现呢?
我们应该会想到一个简单思路:建立一个临时的Temp类暂时放在文件流中,然后进行编译,然后再用java的映射获取临时类中的方法调用即可。
下面是一个例子程序:
import java.io.PrintWriter;
import java.lang.reflect.Method;
public class JavaCT {
public static void main(String args[]){
JavaCT jc = new JavaCT();
jc.eval("liao");
}
public void eval(String str){
//System.out.println(System.getProperty("user.dir"));
String s = "class Temp{";
s += "public static String call(String[] ss){";
s += "System.out.println(\"" + str + "\");";
s += "return \"return str\";";
s += "}}";
try{
java.io.File f = new java.io.File("Temp.java");
PrintWriter pw = new PrintWriter(f);
pw.println(s);
pw.close();
//动态编译
String[] commadline = {"-d",System.getProperty("user.dir"),"Temp.java"};
int status = com.sun.tools.javac.Main.compile(commadline);
if(status != 0) System.out.println("Faile !!!!!");
}catch(Exception e){
System.out.println("编译错误!");
}
try {
Class<?> cls = Class.forName("Temp");
//System.out.println(ClassLoader.getSystemClassLoader().getResource("Temp.java"));
//映射call方法
Method call = cls.getMethod("call", new Class[]{String[].class});
//执行call方法
System.out.println(call.invoke(null, new Object[]{new String[0]}));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("运行错误!");
}
}
}
通过该例子可以知道一个类可以通过字符串创建并执行它,那么只需要把该程序稍微修改就可以变成JS中类似的eval()了。我们只需要修改Temp中的call方法即可。
来源:oschina
链接:https://my.oschina.net/u/146940/blog/62567