如何让Graal.js处理自定义Java数值类型?
解决Graal.js中自定义Number子类的算术运算兼容问题
方案一:给自定义JSNumber类添加valueOf()方法
在你的Java类JSNumber中添加valueOf()方法,返回对应的数值类型,Graal.js在进行算术运算时会自动调用该方法获取数值,而非直接转字符串:
public class JSNumber extends Number { // 原有业务代码... // 添加valueOf方法,返回实际数值 public double valueOf() { return this.doubleValue(); } // 若以整数运算为主,也可返回int类型 // public int valueOf() { // return this.intValue(); // } }
添加后,JS执行e.id + 1时会先调用e.id.valueOf()拿到数值,再和1做加法运算,结果会是2而非12,完全匹配原有Nashorn的行为。
方案二:实现Graal.js运算符重载方法
如果需要精细控制每个运算符的行为,可以给JSNumber添加对应运算符的重载方法。以加法为例:
public class JSNumber extends Number { // 原有业务代码... public Number $add$(Object other) { if (other instanceof Number) { double sum = this.doubleValue() + ((Number) other).doubleValue(); // 根据业务需求返回JSNumber实例或原生数值 return new JSNumber(sum); } // 兼容字符串转数值的场景 if (other instanceof String) { try { double otherVal = Double.parseDouble((String) other); return new JSNumber(this.doubleValue() + otherVal); } catch (NumberFormatException e) { // 按原有逻辑处理非数值字符串的情况 return super.toString() + other; } } return super.toString() + other; } }
同理可实现减法($sub$)、乘法($mul$)等其他运算符的重载方法,完全复刻原有业务逻辑。
方案三:通过上下文配置启用自动类型适配
创建Graal.js的Context时,配置选项让Java的Number子类自动转换为JS原生数值:
Context context = Context.newBuilder("js") .option("js.java-number-to-primitive", "true") .build();
该配置会让Graal.js自动识别JavaNumber子类为数值类型,无需修改JSNumber类即可支持算术运算。注意不同Graal.js版本的配置选项可能略有差异,需对应版本调整。
内容的提问来源于stack exchange,提问作者Erik
相关产品推荐
相关产品推荐

