You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在运行时动态评估来自JSON数据的可变Java表达式?

Java动态评估字符串三元表达式的实现方案

1. 使用Java内置ScriptEngine(无额外依赖)

Java自带的ScriptEngine可以直接执行兼容Java语法的表达式,步骤简单无需引入第三方库:

  • 获取JavaScript引擎实例(Java 8默认用Nashorn,Java 11+推荐GraalVM JS引擎)
  • 将运行时变量绑定到引擎上下文
  • 执行表达式并获取结果

代码示例:

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.util.Map;

public class ScriptEngineEvaluator {
    public static Object evaluate(String expression, Map<String, Object> variables) throws ScriptException {
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("js");
        
        // 绑定运行时变量
        variables.forEach(engine::put);
        
        // 执行表达式
        return engine.eval(expression);
    }

    public static void main(String[] args) throws ScriptException {
        String expr = "value1 < 0 ? 3:5";
        Map<String, Object> vars = Map.of("value1", -2);
        Object result = evaluate(expr, vars);
        System.out.println(result); // 输出3
    }
}

注意:Java 11及以后Nashorn被标记为废弃,需确保GraalVM JS模块可用;高频调用场景要注意引擎的执行开销。

2. 使用Apache Commons JEXL库(推荐复杂/可变场景)

Apache Commons JEXL是专门为动态表达式求值设计的工具,语法与Java高度兼容,扩展性强,适合表达式未来可能变更的场景。

步骤:

  1. 引入Maven依赖:
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-jexl3</artifactId>
    <version>3.3</version>
</dependency>
  1. 编写求值代码:
import org.apache.commons.jexl3.JexlBuilder;
import org.apache.commons.jexl3.JexlEngine;
import org.apache.commons.jexl3.JexlExpression;
import org.apache.commons.jexl3.MapContext;
import java.util.Map;

public class JexlEvaluator {
    private static final JexlEngine JEXL_ENGINE = new JexlBuilder().create();

    public static Object evaluate(String expression, Map<String, Object> variables) {
        // 编译表达式(可缓存编译结果提升重复调用性能)
        JexlExpression expr = JEXL_ENGINE.createExpression(expression);
        MapContext context = new MapContext();
        variables.forEach(context::set);
        
        return expr.evaluate(context);
    }

    public static void main(String[] args) {
        String expr = "value1 < 0 ? 3:5";
        Map<String, Object> vars = Map.of("value1", 4);
        Object result = evaluate(expr, vars);
        System.out.println(result); // 输出5
    }
}

优势:支持复杂表达式(逻辑运算、函数调用等),编译后的表达式可复用,适配未来表达式的扩展需求。

3. 自定义简单解析器(仅适用于固定格式三元表达式)

如果表达式始终是条件 ? 真分支 : 假分支的极简格式,可自己拆分表达式求值,避免依赖,但局限性极大,表达式格式变更后需同步修改解析逻辑:

代码示例:

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.util.Map;

public class SimpleTernaryEvaluator {
    public static Object evaluate(String expression, Map<String, Object> variables) {
        // 拆分最外层的三元运算符(跳过括号内的内容)
        int questionMarkIdx = findOuterOperator(expression, '?');
        int colonIdx = findOuterOperator(expression.substring(questionMarkIdx + 1), ':') + questionMarkIdx + 1;

        String conditionStr = expression.substring(0, questionMarkIdx).trim();
        String trueBranch = expression.substring(questionMarkIdx + 1, colonIdx).trim();
        String falseBranch = expression.substring(colonIdx + 1).trim();

        // 评估条件
        boolean condition = evaluateCondition(conditionStr, variables);
        
        // 返回对应分支结果
        return condition ? parseBranch(trueBranch, variables) : parseBranch(falseBranch, variables);
    }

    private static boolean evaluateCondition(String condition, Map<String, Object> variables) {
        try {
            ScriptEngine engine = new ScriptEngineManager().getEngineByName("js");
            variables.forEach(engine::put);
            return (boolean) engine.eval(condition);
        } catch (ScriptException e) {
            throw new RuntimeException("条件解析失败", e);
        }
    }

    private static Object parseBranch(String branch, Map<String, Object> variables) {
        if (variables.containsKey(branch)) {
            return variables.get(branch);
        }
        // 尝试解析数字常量
        try {
            return Integer.parseInt(branch);
        } catch (NumberFormatException e) {
            try {
                return Double.parseDouble(branch);
            } catch (NumberFormatException ex) {
                throw new RuntimeException("分支解析失败", ex);
            }
        }
    }

    // 找到最外层的运算符(忽略括号内的)
    private static int findOuterOperator(String str, char operator) {
        int bracketCount = 0;
        for (int i = 0; i < str.length(); i++) {
            char c = str.charAt(i);
            if (c == '(') bracketCount++;
            else if (c == ')') bracketCount--;
            else if (c == operator && bracketCount == 0) {
                return i;
            }
        }
        throw new IllegalArgumentException("找不到合法的" + operator + "运算符");
    }

    public static void main(String[] args) {
        String expr = "value1 < 0 ? 3:5";
        Map<String, Object> vars = Map.of("value1", -1);
        Object result = evaluate(expr, vars);
        System.out.println(result); // 输出3
    }
}

注意:此方式仅适合极简场景,表达式一旦引入复杂逻辑(如括号、&&/||运算),解析逻辑会急剧复杂化。


内容的提问来源于stack exchange,提问作者Brian Figueroa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 22:51:01