Java 字符串表达式计算
在 Java 中计算字符串表达式有几种常见方法,以下是几种实现方式:

使用 ScriptEngine (Nashorn)
Java 8+ 内置了 Nashorn JavaScript 引擎,可以用来计算 JavaScript 表达式:
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
public class StringExpressionEvaluator {
public static void main(String[] args) {
ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
try {
// 计算简单表达式
Object result = engine.eval("2 + 3 * 4");
System.out.println(result); // 输出: 14
// 计算复杂表达式
result = engine.eval("(5 + 3) * (10 - 4) / 2");
System.out.println(result); // 输出: 24
// 使用变量
engine.eval("var x = 10; var y = 20;");
result = engine.eval("x + y * 2");
System.out.println(result); // 输出: 50
} catch (ScriptException e) {
e.printStackTrace();
}
}
}
使用第三方库 (exp4j)
exp4j 是一个专门用于数学表达式计算的轻量级库:
import net.objecthunter.exp4j.Expression;
import net.objecthunter.exp4j.ExpressionBuilder;
public class Exp4jExample {
public static void main(String[] args) {
// 创建表达式
Expression e = new ExpressionBuilder("x + y * z")
.variables("x", "y", "z")
.build()
.setVariable("x", 2)
.setVariable("y", 3)
.setVariable("z", 4);
try {
double result = e.evaluate();
System.out.println(result); // 输出: 14.0
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
使用第三方库 (MVEL)
MVEL 是一个功能强大的表达式语言和引擎:
import org.mvel2.MVEL;
import java.util.HashMap;
import java.util.Map;
public class MvelExample {
public static void main(String[] args) {
String expression = "x + y * z";
Map<String, Object> variables = new HashMap<>();
variables.put("x", 2);
variables.put("y", 3);
variables.put("z", 4);
Object result = MVEL.eval(expression, variables);
System.out.println(result); // 输出: 14
}
}
自定义解析器 (简单实现)
对于简单表达式,可以自己实现一个基本的解析器:

import java.util.Stack;
public class SimpleExpressionEvaluator {
public static double evaluate(String expression) {
Stack<Double> numbers = new Stack<>();
Stack<Character> ops = new Stack<>();
for (int i = 0; i < expression.length(); i++) {
char c = expression.charAt(i);
if (c == ' ') continue;
if (Character.isDigit(c) || c == '.') {
StringBuilder sb = new StringBuilder();
while (i < expression.length() &&
(Character.isDigit(expression.charAt(i)) || expression.charAt(i) == '.')) {
sb.append(expression.charAt(i++));
}
i--;
numbers.push(Double.parseDouble(sb.toString()));
} else if (c == '(') {
ops.push(c);
} else if (c == ')') {
while (ops.peek() != '(') {
numbers.push(applyOp(ops.pop(), numbers.pop(), numbers.pop()));
}
ops.pop();
} else if (isOperator(c)) {
while (!ops.isEmpty() && hasPrecedence(c, ops.peek())) {
numbers.push(applyOp(ops.pop(), numbers.pop(), numbers.pop()));
}
ops.push(c);
}
}
while (!ops.isEmpty()) {
numbers.push(applyOp(ops.pop(), numbers.pop(), numbers.pop()));
}
return numbers.pop();
}
private static boolean isOperator(char c) {
return c == '+' || c == '-' || c == '*' || c == '/';
}
private static boolean hasPrecedence(char op1, char op2) {
if (op2 == '(' || op2 == ')') return false;
return (op1 != '*' && op1 != '/') || (op2 != '+' && op2 != '-');
}
private static double applyOp(char op, double b, double a) {
switch (op) {
case '+': return a + b;
case '-': return a - b;
case '*': return a * b;
case '/':
if (b == 0) throw new UnsupportedOperationException("Cannot divide by zero");
return a / b;
}
return 0;
}
public static void main(String[] args) {
String expression = "3 + 5 * 2 - 8 / 4";
System.out.println(evaluate(expression)); // 输出: 12.0
}
}
使用 Java 8 的 ScriptEngine (更安全的版本)
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
public class SafeExpressionEvaluator {
public static double evaluate(String expression) throws ScriptException {
ScriptEngine engine = new ScriptEngineManager().getEngineByName("js");
// 使用 Function 包装表达式,避免直接执行任意代码
String wrapped = "function evaluate() { return " + expression + "; }";
engine.eval(wrapped);
Object result = engine.eval("evaluate();");
return ((Number) result).doubleValue();
}
public static void main(String[] args) {
try {
System.out.println(evaluate("2 + 3 * 4")); // 14.0
System.out.println(evaluate("(5 + 3) * (10 - 4) / 2")); // 24.0
} catch (ScriptException e) {
System.err.println("Invalid expression: " + e.getMessage());
}
}
}
安全注意事项
当处理来自不可信源的字符串表达式时,需要注意安全风险:
- 避免直接执行任意代码(如 Nashorn 可以执行任意 JavaScript 代码)
- 考虑使用沙箱环境或限制可用的操作
- 对输入进行验证和清理
- 对于数学表达式,优先选择专门的数学表达式库(如 exp4j)
方法各有优缺点,选择哪种方法取决于你的具体需求、性能要求和安全性考虑。
