在 java 中评估包含逻辑运算的字符串作为布尔值
Evaluating a string holding a logic operation as a Boolean in java
我正在尝试将 "in1 && in2"
评估为布尔值作为测试,但我希望能够将所有布尔值评估为我的实际项目的 stings。 in1 和 in2 是具有布尔状态的节点的名称,我得到这样的实际表达式,
logic = logic.replaceAll(curName, (nodes.get(ins.get(j)).getState() ? "true" : "false"));
logic 是联系我想要评估的逻辑的字符串,curname 是当前节点名称被替换为它的布尔值(例如“in1”)它在一个循环中所以所有节点名称在评估字符串之前被替换, nodes 是节点数组列表,ins 是节点数组中输入节点的索引,getState()
returns 节点布尔值这很好用,将逻辑字符串的新值设置为“true” && 真。
困难的部分是将字符串作为布尔值求值。我发现我可以使用 javax.script 来帮助我 here。所以我就这样实现了
ScriptEngineManager sem = new ScriptEngineManager();
ScriptEngine se = sem.getEngineByName("JavaScript");
nodes.get(outs.get(i)).setState((boolean)se.eval(logic));
问题是它每次都计算为 false,当我尝试将 eval 返回的对象转换为布尔值并尝试像这样显示它时,
System.out.printLine(String.valueOf((boolean)se.eval(logic)));
它只是 returns 错误。
在 oracle's page on eval 上,我发现还有一些其他参数可以传递给 eval,我是缺少其中一个还是完全是其他参数?
*旁注,我在这里没有显示的任何代码都不是问题,我已经用原始布尔值而不是字符串测试了评估。
无需修改脚本。只需将值作为变量发送。
public static void main(String[] args) throws Exception {
test(false, false);
test(false, true );
test(true , false);
test(true , true );
}
private static void test(boolean in1, boolean in2) throws ScriptException {
ScriptEngineManager engineManager = new ScriptEngineManager();
ScriptEngine engine = engineManager.getEngineByName("JavaScript");
Bindings vars = engine.getBindings(ScriptContext.ENGINE_SCOPE);
vars.put("in1", in1);
vars.put("in2", in2);
boolean result = (boolean) engine.eval("in1 && in2");
System.out.println(result);
}
输出
false
false
false
true
您甚至可以预编译脚本以获得更好的性能。
public class Test {
public static void main(String[] args) throws Exception {
Test test = new Test();
System.out.println(test.test(false, false));
System.out.println(test.test(false, true ));
System.out.println(test.test(true , false));
System.out.println(test.test(true , true ));
}
private ScriptEngine jsEngine;
private CompiledScript script;
private Test() throws ScriptException {
this.jsEngine = new ScriptEngineManager().getEngineByName("JavaScript");
this.script = ((Compilable) this.jsEngine).compile("in1 && in2");
}
private boolean test(boolean in1, boolean in2) throws ScriptException {
Bindings vars = this.jsEngine.createBindings();
vars.put("in1", in1);
vars.put("in2", in2);
return (boolean) this.script.eval(vars);
}
}
我正在尝试将 "in1 && in2"
评估为布尔值作为测试,但我希望能够将所有布尔值评估为我的实际项目的 stings。 in1 和 in2 是具有布尔状态的节点的名称,我得到这样的实际表达式,
logic = logic.replaceAll(curName, (nodes.get(ins.get(j)).getState() ? "true" : "false"));
logic 是联系我想要评估的逻辑的字符串,curname 是当前节点名称被替换为它的布尔值(例如“in1”)它在一个循环中所以所有节点名称在评估字符串之前被替换, nodes 是节点数组列表,ins 是节点数组中输入节点的索引,getState()
returns 节点布尔值这很好用,将逻辑字符串的新值设置为“true” && 真。
困难的部分是将字符串作为布尔值求值。我发现我可以使用 javax.script 来帮助我 here。所以我就这样实现了
ScriptEngineManager sem = new ScriptEngineManager();
ScriptEngine se = sem.getEngineByName("JavaScript");
nodes.get(outs.get(i)).setState((boolean)se.eval(logic));
问题是它每次都计算为 false,当我尝试将 eval 返回的对象转换为布尔值并尝试像这样显示它时,
System.out.printLine(String.valueOf((boolean)se.eval(logic)));
它只是 returns 错误。
在 oracle's page on eval 上,我发现还有一些其他参数可以传递给 eval,我是缺少其中一个还是完全是其他参数?
*旁注,我在这里没有显示的任何代码都不是问题,我已经用原始布尔值而不是字符串测试了评估。
无需修改脚本。只需将值作为变量发送。
public static void main(String[] args) throws Exception {
test(false, false);
test(false, true );
test(true , false);
test(true , true );
}
private static void test(boolean in1, boolean in2) throws ScriptException {
ScriptEngineManager engineManager = new ScriptEngineManager();
ScriptEngine engine = engineManager.getEngineByName("JavaScript");
Bindings vars = engine.getBindings(ScriptContext.ENGINE_SCOPE);
vars.put("in1", in1);
vars.put("in2", in2);
boolean result = (boolean) engine.eval("in1 && in2");
System.out.println(result);
}
输出
false
false
false
true
您甚至可以预编译脚本以获得更好的性能。
public class Test {
public static void main(String[] args) throws Exception {
Test test = new Test();
System.out.println(test.test(false, false));
System.out.println(test.test(false, true ));
System.out.println(test.test(true , false));
System.out.println(test.test(true , true ));
}
private ScriptEngine jsEngine;
private CompiledScript script;
private Test() throws ScriptException {
this.jsEngine = new ScriptEngineManager().getEngineByName("JavaScript");
this.script = ((Compilable) this.jsEngine).compile("in1 && in2");
}
private boolean test(boolean in1, boolean in2) throws ScriptException {
Bindings vars = this.jsEngine.createBindings();
vars.put("in1", in1);
vars.put("in2", in2);
return (boolean) this.script.eval(vars);
}
}