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

时间:2014-07-28 12:01:21

标签: 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}

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

任何?


修改

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

4 个答案:

答案 0 :(得分:16)

查看java scripting 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 在某处拦截所有未知的自由变量。

答案 1 :(得分:6)

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

答案 2 :(得分:1)

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

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

这将在类路径中创建一个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 = " + <your_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<? extends JavaFileObject> 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();
}
}

答案 3 :(得分:1)

我认为更好的解决方案是更改您的架构,但如果您被迫尝试以下内容:)您可以找到此代码here

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<StandardJavaFileManager> {

        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<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();
        JavaFileObject file = new JavaSourceFromString(className, classBody);
        Iterable<? extends JavaFileObject> 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<? extends JavaFileObject> 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> T newProxyInstance(Class<T> 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));
    }

}