JDK 1.8.0_92 Nashorn JS引擎indexOf行为

时间:2016-07-01 08:17:15

标签: javascript arrays java-8 nashorn

我在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版本之间的结果有这样的差异?这是一个错误还是故意改变了?

2 个答案:

答案 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));

希望这会有所帮助:)