话不多说,直接上代码:
package Test;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.net.URI;
import java.util.Arrays;
import javax.tools.FileObject;
import javax.tools.ForwardingJavaFileManager;
import javax.tools.JavaCompiler;
import javax.tools.SimpleJavaFileObject;
import javax.tools.ToolProvider;
import javax.tools.JavaCompiler.CompilationTask;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
import javax.tools.JavaFileObject.Kind;
public class MyTest2 {
public static class StringSourceJavaObject extends SimpleJavaFileObject{
private String content = null;
protected StringSourceJavaObject(String name, String content) {
super(URI.create("string:///"+name.replace('.', '/')+Kind.SOURCE.extension), Kind.SOURCE);
this.content = content;
}
public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException{
return this.content;
}
}
static class JavaClassFileObject extends SimpleJavaFileObject{
ByteArrayOutputStream outputStream=null;
public JavaClassFileObject(String className, Kind kind) {
super(URI.create("string:///"+className.replace('.', '/')+kind.extension), kind);
outputStream = new ByteArrayOutputStream();
}
@Override
public OutputStream openOutputStream() throws IOException{
return this.outputStream;
}
public byte[] getClassBytes(){
return outputStream.toByteArray();
}
}
static class ClassFileManager extends ForwardingJavaFileManager<JavaFileManager>{
private JavaClassFileObject classFileObject;
protected ClassFileManager(JavaFileManager fileManager) {
super(fileManager);
}
@Override
public JavaFileObject getJavaFileForOutput(Location location,String className,Kind kind,FileObject sibling) throws IOException{
classFileObject = new JavaClassFileObject(className, kind);
return classFileObject;
}
@Override
public ClassLoader getClassLoader(Location location){
return new ClassLoader() {
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException{
byte[] classBytes = classFileObject.getClassBytes();
return super.defineClass(name, classBytes, 0, classBytes.length);
}
};
}
}
public static double calculate(String expr) {
String className = "CalculatorMainA";
String methodName = "calculate";
String source = "package Test; public class "+className +
" {public static double "+methodName + " () {return "+ expr+";}}";
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
JavaFileManager fileManager = new ClassFileManager(compiler.getStandardFileManager(null, null, null));
StringSourceJavaObject javaObject = new StringSourceJavaObject("Test.CalculatorMainA", source);
CompilationTask task = compiler.getTask(null, fileManager, null, null, null, Arrays.asList(javaObject));
if(task.call()){
ClassLoader loader = fileManager.getClassLoader(null);
try{
Class<?> clazz = loader.loadClass("Test.CalculatorMainA");
Method method = clazz.getMethod(methodName, new Class<?>[]{});
Object value = method.invoke(null, new Object[]{});
return (Double)value;
}catch (Exception e) {
e.printStackTrace();
}
}
return 0;
}
public static void main(String[] args) {
double d = calculate("1+2*2");
System.out.println(d);
}
}
本文介绍了一种使用Java进行动态编译与执行表达式的实现方法。通过自定义`StringSourceJavaObject`来提供源代码,并利用`JavaCompiler`进行编译,最终通过反射调用编译后的类的方法获取结果。
1290

被折叠的 条评论
为什么被折叠?



