2016-04-25 80 views
6

我們從Oracle JDK 8u77升級到8u92,突然之前正在工作的腳本不再有效。一個最小的再現是:Nashorn不再使用BigDecimal

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似乎表明否則。

回答

7

Nashorn的初始版本將所有數字Java原語和java.lang.Number的所有子類都視爲JavaScript數字。然而,JavaScript數字定義爲雙精度,這意味着數字類型不會映射爲雙精度(如longs或java.lang.BigDecimals),但轉換爲JavaScript數字時將會失去精度。

正如您所注意到的,我們在8u77和8u92之間修正了這個問題。不能將乾淨地映射到雙精度的java.lang.Number實例不再視爲Nashorn中的JavaScript數字。

有兩種方法可以解決這個問題。一種是將這些數字視爲Java對象,並使用Java類提供的方法。這通常是更好的選擇,因爲Java類被編寫用於處理數字類型。另一種選擇是顯式轉換爲JavaScript數字。這通常是通過調用沒有「new」關鍵字的全局Number()構造函數,或者通過預先加入一元「+」運算符來完成的。但請注意,如果不注意,此轉換可能會導致精度損失,因此第一個選項可能是更安全的路徑。

+0

我在JDK 8發行說明中沒有發現任何提及。 @ hannes-wallnöfer引用的錯誤是https://bugs.openjdk.java.net/browse/JDK-8146264 –