我们从Oracle JDK 8u77升级到8u92,突然以前无法运行的脚本不再起作用。最小的复制器是:
Map<String, Object> attributes = Collections.singletonMap("GROSSREIMBAMOUNT", BigDecimal.ZERO);
String script = "GROSSREIMBAMOUNT.toFixed(2)";
ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine jsEngine = mgr.getEngineByName("JavaScript");
for (Entry<String, Object> entry : attributes.entrySet()) {
jsEngine.put(entry.getKey(), entry.getValue());
}
System.out.println(jsEngine.eval(script));
以前我们有
0.00
但是现在我们得到了。
TypeError: GROSSREIMBAMOUNT.toFixed is not a function
typeof
现在返回object
以前返回的位置number
。
我的问题是这种行为是故意的还是错误?我首先虽然这将是一个错误,但JDK-8010732似乎暗示了其他问题。
Nashorn的初始发行版将所有数字Java原语和java.lang.Number的所有子类都视为JavaScript数字。但是,JavaScript数字定义为双精度型,这意味着不能转换为双精度型的数字类型(例如long或java.lang.BigDecimals)在转换为JavaScript数字时会失去精度。
如您所见,我们将其固定在8u77和8u92之间。无法干净地映射为double的java.lang.Number实例在Nashorn中不再被视为JavaScript数字。
您可以通过两种方法解决此问题。一种是将这些数字视为Java对象,并使用Java类提供的方法。通常,这是更好的选择,因为Java类是为与手头的数字类型一起使用而编写的。另一个选择是显式转换为JavaScript数字。通常,可以通过调用不带“ new”关键字的全局Number()构造函数来完成此操作,也可以仅在前加一元“ +”运算符。但是请注意,这种转换可能会导致精度损失,而不会引起您的注意,因此第一种选择可能是更安全的路径。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句