java執(zhí)行字符串公式的三種方法總結(jié)
問題描述
最近,在項目中遇到了一項特定需求:前端用戶需要輸入一個數(shù)學公式,這個公式隨后被保存到后臺數(shù)據(jù)庫中。當后臺需要從數(shù)據(jù)庫中檢索這個公式并進行計算時,面臨的一個挑戰(zhàn)是,從數(shù)據(jù)庫獲取的公式是以字符串形式存在的,無法直接代入數(shù)值進行計算。
解決方案
方法1:使用 ScriptEngine(Java內(nèi)置)
經(jīng)查閱資料,發(fā)現(xiàn)利用Java的腳本引擎(特別是JavaScript引擎)能夠高效地解析并執(zhí)行各類數(shù)學公式。在JDK 1.6及更高版本中,引入了javax.script包,這一包為開發(fā)者提供了極大的便利,能夠輕松地將腳本引擎嵌入到Java應(yīng)用程序中。借助這一功能,我們可以無縫地處理字符串形式的公式,并將其轉(zhuǎn)化為可執(zhí)行的代碼,從而滿足項目中的計算需求。
具體代碼:
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
public class EvaluateExpression {
public static void main(String[] args) {
// 示例公式字符串(從數(shù)據(jù)庫中獲取)
String expression = "3 + 5 * (2 - 8)";
// 創(chuàng)建一個腳本引擎管理器
ScriptEngineManager manager = new ScriptEngineManager();
// 獲取一個JavaScript引擎
ScriptEngine engine = manager.getEngineByName("JavaScript");
try {
// 執(zhí)行公式并獲取結(jié)果
Object result = engine.eval(expression);
// 將結(jié)果轉(zhuǎn)換為字符串并打印
System.out.println("公式" + expression + "的執(zhí)行結(jié)果是:"+ result);
} catch (ScriptException e) {
// 捕獲并處理腳本異常
System.err.println(e.getMessage());
}
}
}
運行結(jié)果

注:如果公式中包含變量作為運算的一部分,我們可以通過使用Java字符串的replace()或者replaceAll()方法,將這些變量替換為具體的數(shù)值,隨后再進行計算。以下是一個具體的代碼實現(xiàn)示例,用于說明這一過程:
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
public class EvaluateExpression {
public static void main(String[] args) {
// 示例公式字符串(從數(shù)據(jù)庫中獲取)
String expression = "3 + a * (2 - b) + a";
// 創(chuàng)建一個腳本引擎管理器
ScriptEngineManager manager = new ScriptEngineManager();
// 獲取一個JavaScript引擎
ScriptEngine engine = manager.getEngineByName("JavaScript");
String a = "5", b = "8";
try {
// 執(zhí)行公式并獲取結(jié)果
Object result = engine.eval(expression.replaceAll("a", a).replace("b", b));
// 將結(jié)果轉(zhuǎn)換為字符串并打印
System.out.println("公式" + expression + "的執(zhí)行結(jié)果是:"+ result);
} catch (ScriptException e) {
// 捕獲并處理腳本異常
System.err.println(e.getMessage());
}
}
}
運行結(jié)果

注意:Java 9+ 已將 Nashorn 引擎標記為廢棄(需手動添加依賴),且存在安全風險。建議對非受信輸入進行嚴格校驗。
方法2:使用第三方庫 [exp4j](推薦)
官網(wǎng)地址: exp4j
適用于數(shù)學表達式(安全且輕量級):
- 添加依賴(Maven):
<dependency>
<groupId>net.objecthunter</groupId>
<artifactId>exp4j</artifactId>
<version>0.4.8</version>
</dependency>
- 示例代碼:
import net.objecthunter.exp4j.Expression;
import net.objecthunter.exp4j.ExpressionBuilder;
public class FormulaCalculator {
public static void main(String[] args) {
String formula = "10 * (3 + 2) / 5";
Expression expression = new ExpressionBuilder(formula).build();
double result = expression.evaluate();
System.out.println(result); // 輸出: 10.0
}
}
優(yōu)勢:
- 無外部依賴,避免代碼注入風險
- 支持自定義變量(如
"x^2 + y") - 支持數(shù)學函數(shù)(
sin,log等)
方法3:使用Expression(Spring框架)(推薦)
適用于 Spring 項目:
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
public class FormulaCalculator {
public static void main(String[] args) {
String formula = "10 * (3 + 2) / 5";
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression(formula);
Integer result = exp.getValue(Integer.class);
System.out.println(result); // 輸出: 10
}
}
總結(jié)
javax.script包中的ScriptEngineManager腳本引擎管理器是一個功能強大的工具,它能夠滿足我們在Java代碼中執(zhí)行字符串公式的需求。通過ScriptEngineManager,我們可以輕松地獲取到各種腳本引擎(如JavaScript引擎),并利用這些引擎來解析和執(zhí)行嵌入在字符串中的數(shù)學表達式或其他類型的腳本代碼。這種方法不僅簡化了代碼的實現(xiàn),還提高了程序的靈活性和可擴展性,使我們能夠高效地處理各種復(fù)雜的計算任務(wù)。
雖然ScriptEngine能滿足需求,但對Java 9+兼容性較差??紤]到目前大多數(shù)企業(yè)都采用Spring全家桶進行開發(fā),我們強烈推薦使用Spring Expression。當然exp4j也是很不錯的選擇。
到此這篇關(guān)于java執(zhí)行字符串公式的三種方法的文章就介紹到這了,更多相關(guān)java執(zhí)行字符串公式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring Boot集成Spring Cloud Security進行安全增強的方法
Spring Cloud Security是Spring Security的擴展,它提供了對Spring Cloud體系中的服務(wù)認證和授權(quán)的支持,包括OAuth2、JWT等,這篇文章主要介紹了Spring Boot集成Spring Cloud Security進行安全增強,需要的朋友可以參考下2024-11-11
Oracle+Mybatis的foreach insert批量插入報錯的快速解決辦法
本文給大家介紹Oracle+Mybatis的foreach insert批量插入報錯的快速解決辦法,非常不錯,具有參考借鑒價值,感興趣的朋友參考下吧2016-08-08
SpringBoot中使用異步調(diào)度程序的高級方法
本文主要介紹了SpringBoot中使用異步調(diào)度程序的高級方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2024-07-07

