将字符串转换为Java中的代码

我遇到了一个奇怪的案子。 在给定的数据库中,我得到了一个具有VARCHAR字段的记录,因此在我的实体模型中,我添加了此字段,以及getter和setter。 现在是有趣的开始点:

下面的字符串实际上是方法的主体。 它看起来像这样:

 if (score <= 0.7) {return 0;} else if (score <=0.8) {return 1;} else if (score <=0.9) {return 2;} else {return 3} 

现在 – 我需要将这个字符串变成一个方法,说实话我不知道如何实现这一点。 这个实际的方法需要从我得到一个得分为double,并根据给定的分数返回一个整数值。

任何人?


编辑

我知道最简单的方法是不使用这样的解决方案,但这不是我的号召,此外,数据库中有大量这样的记录,每条记录都不同。 我们无法解决这个问题。 我必须处理这个问题 – 所以请求解决方案的想法,我保证我会做所有的讨厌,并说这是愚蠢的:)
相信我,我和我一样,我会抱怨很长一段时间。

查看java脚本API

 int eval(String code) { code = "function f () {" + code + "} f()"; // Or otherwise ScriptEngineManager factory = new ScriptEngineManager(); ScriptEngine engine = factory.getEngineByName("JavaScript"); engine.put("score", 1.4); Number num = (Number) engine.eval(code); return num.intValue(); } 

在这里我假设,JavaScript语法是可能的; 不得不填写score ,你可能会在某处拦截所有未知的自由变量。

您应该查看Java Scripting API 。 有几个实现此API的项目允许您添加运行Java代码脚本的function。

最好的方法是使用Scripting API,正如大多数回答者已经指出的那样。 你可以从那里运行JavaScript。 如果你想要更多并且尝试运行Java代码(并且作为一个eretic指出),你可以尝试使用JavaCompiler编译代码并使用类加载器运行它。

请注意:这是使用Java的最ORRIFIC方法之一。 你应该只使用它来调试,并且只能作为最后的希望。 绝不应该在生产环境中使用它。

这将在类路径中创建一个DontTryThisAtHome.java文件。 记住只使用这种策略来获得乐趣和极少数其他情况:

 public class MyClass{ public static void main(String[] args) throws Exception { JavaCompiler jc = ToolProvider.getSystemJavaCompiler(); StandardJavaFileManager sjfm = jc.getStandardFileManager(null, null, null); File jf = new File("DontTryThisAtHome.java"); PrintWriter pw = new PrintWriter(jf); pw.println("public class DontTryThisAtHome{" + "static final int score = " +  + ";" + "public static void main(){}" + "public int getValue(){" + " return score<=0.7?0:score<=0.8?1: score<=0.9?2:3" + "} + "}"); pw.close(); Iterable fO = sjfm.getJavaFileObjects(jf); if(!jc.getTask(null,sjfm,null,null,null,fO).call()) { throw new Exception("compilation failed"); } URL[] urls = new URL[]{new File("").toURI().toURL()}; URLClassLoader ucl = new URLClassLoader(urls); Object o= ucl.loadClass("DontTryThisAtHome").newInstance(); int result = (int) o.getClass().getMethod("getValue").invoke(o); ucl.close(); } } 

我认为更好的解决方案是改变你的架构,但如果你被迫尝试以下:)这个代码你可以在这里找到

 public class DynamicProxy { public interface CalculateScore { double calculate(double score); } private static class JavaSourceFromString extends SimpleJavaFileObject { final String code; JavaSourceFromString(String name, String code) { super(URI.create("string:///" + name.replace('.', '/') + Kind.SOURCE.extension), Kind.SOURCE); this.code = code; } @Override public CharSequence getCharContent(boolean ignoreEncodingErrors) { return code; } } private static class JavaClassObject extends SimpleJavaFileObject { protected final ByteArrayOutputStream bos = new ByteArrayOutputStream(); public JavaClassObject(String name, Kind kind) { super(URI.create("string:///" + name.replace('.', '/') + kind.extension), kind); } public byte[] getBytes() { return bos.toByteArray(); } @Override public OutputStream openOutputStream() throws IOException { return bos; } } private static class ClassFileManager extends ForwardingJavaFileManager { private JavaClassObject classObject; private final String className; public ClassFileManager(StandardJavaFileManager standardManager, String className) { super(standardManager); this.className = className; } @Override public ClassLoader getClassLoader(Location location) { return new SecureClassLoader(DynamicProxy.class.getClassLoader()) { @Override protected Class findClass(String name) throws ClassNotFoundException { if (name.contains(className)) { byte[] b = classObject.getBytes(); return super.defineClass(name, classObject.getBytes(), 0, b.length); } return super.findClass(name); } }; } @Override public JavaFileObject getJavaFileForOutput(Location location, String className, javax.tools.JavaFileObject.Kind kind, FileObject sibling) throws IOException { classObject = new JavaClassObject(className, kind); return classObject; } } private static class MyInvocationHandler implements InvocationHandler { private final String className; private final String classBody; public MyInvocationHandler(String implClassName, String classBody) { this.className = implClassName; this.classBody = classBody; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Class clazz = compileClass(className, classBody); return method.invoke(clazz.newInstance(), args); } } private static Class compileClass(String className, String classBody) throws Throwable { JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); DiagnosticCollector diagnostics = new DiagnosticCollector(); JavaFileObject file = new JavaSourceFromString(className, classBody); Iterable compilationUnits = Arrays.asList(file); JavaFileManager fileManager = new ClassFileManager(compiler.getStandardFileManager(null, null, null), className); CompilationTask task = compiler.getTask(null, fileManager, diagnostics, null, null, compilationUnits); boolean success = task.call(); for (Diagnostic diagnostic : diagnostics.getDiagnostics()) { System.out.println(diagnostic.getCode()); System.out.println(diagnostic.getKind()); System.out.println(diagnostic.getPosition()); System.out.println(diagnostic.getStartPosition()); System.out.println(diagnostic.getEndPosition()); System.out.println(diagnostic.getSource()); System.out.println(diagnostic.getMessage(null)); } if (success) { return fileManager.getClassLoader(null).loadClass(className); } return null; } @SuppressWarnings("unchecked") public static  T newProxyInstance(Class clazz, String className, String classBody) { ClassLoader parentLoader = DynamicProxy.class.getClassLoader(); return (T) Proxy.newProxyInstance(parentLoader, new Class[] { clazz }, new MyInvocationHandler(className, classBody)); } public static CalculateScore create(String body) { StringWriter writer = new StringWriter(); PrintWriter out = new PrintWriter(writer); out.println("public class CalculateScoreImpl implements pl.softech.stackoverflow.javac.DynamicProxy.CalculateScore {"); out.println(" public double calculate(double score) {"); out.println(body); out.println(" }"); out.println("}"); out.close(); return newProxyInstance(CalculateScore.class, "CalculateScoreImpl", writer.toString()); } public static void main(String[] args) { CalculateScore calculator = create("if (score <= 0.7) {return 0;} else if (score <=0.8) {return 1;} else if (score <=0.9) {return 2;} else {return 3; }"); System.out.println(calculator.calculate(0.3)); } }