我在java8中使用“nashorn”javascript引擎来评估运行时的一些表达式。我有一个用于此方法的util类:
public static String evaluateJavaScriptExpression(String expression) throws ScriptException {
if (expression == null) {
return null;
}
ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
ScriptEngine javaScriptEngine = scriptEngineManager.getEngineByName(JAVASCRIPT_ENGINE);
return String.valueOf(javaScriptEngine.eval(expression));
}
我创建了一些单元测试。其中一个是这样的:
String expression = "var arr = [1, 3, 2, 5, 4]; arr.indexOf(0);";
assertEquals("-1", ExpressionEvaluatorUtil.evaluateJavaScriptExpression(expression));
当我使用java版“1.8.0_91”时,它对我来说很好。但是使用java版“1.8.0_92”的人报告说测试失败了。我将我的版本改为92版,但对我来说也失败了。它的实际结果是“-1.0”。 此外,我在Chrome控制台中尝试了相同的js代码,它在构建91中返回“-1”。
有谁知道为什么两个jdk版本之间的结果有这样的差异?这是一个错误还是故意改变了?
答案 0 :(得分:4)
好吧,如果你知道更改的确切版本号,你知道在哪里看:the list of 1.8u92 bugfixes列出了一些关于Nashorn的修复,最有趣的是JDK-8144020:
删除long作为内部数字类型
ECMA将double定义为JavaScript中唯一的数字类型。在Nashorn,我们在内部将数字表示为int,long和double。使用long是有问题的,因为它为double提供的53位增加了额外的精度。 ...
乍一看,这似乎只是一个内部变化,但如果你意识到你以前的结果源于之前的事实,eval
为此返回了Long
,那么情况会发生变化代码,格式为"-1"
。
现在考虑这个错误报告的第一句话:“ ECMA将double定义为JavaScript中唯一的数字类型”。这导致得出结论:返回Long
不是指定的结果类型,而是实现工件。
显然,当long
从内部使用中移除时,返回Long
的可能性被消除,引擎现在不会返回Integer
,而是Double
},作为改变的副产品。
这解释了为什么还有像"var str = 'abcd'; str.indexOf('x');"
这样的其他脚本仍会产生没有小数位的输出。后一个脚本评估为Integer
,但仍然如此。由于输出类型的更改是删除内部long
用法的副产品,而不是更改所有非Double
数字结果的有意操作,因此内部使用int
的地方不会受到影响。< / p>
将结果与Chrome引擎进行比较时,您必须考虑只是比较格式化输出,而字符串转换的数字不是脚本的一部分。所以结果没有具体说明。浏览器可以自由地显示与整数值匹配的所有数值,而不包含小数位。
答案 1 :(得分:0)
如果我们查看java documentation for ScriptEngine。eval(字符串输入)方法,它会返回一个对象,然后由开发人员根据返回类型的javascript对类型进行类型转换以更正类型。所以,我认为问题是用String.valueOf()方法调用,表达式的Evalu表返回一个浮点数。
我认为您必须将代码更改为Integer.valueOf(javaScriptEngine.eval(expression));
希望这会有所帮助:)