Java 计算器,通过动态生成并编译Java类来进行

本文介绍了一种使用Java进行动态编译与执行表达式的实现方法。通过自定义`StringSourceJavaObject`来提供源代码,并利用`JavaCompiler`进行编译,最终通过反射调用编译后的类的方法获取结果。

话不多说,直接上代码:

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);
	}
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值