You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

OpenJDK Nashorn与内置Nashorn的Array push类型转换差异问题

从JDK内置Nashorn迁移到OpenJDK Nashorn的数组类型转换问题

问题现象

将代码从JDK 11内置的Nashorn切换到OpenJDK Nashorn时,出现以下类型不一致问题:

var testArray = [];
testArray.push(new java.lang.Long(1234));
// 结果:数组元素为java.lang.Double类型

var testTwoArray = [new java.lang.Long(1234)];
// 结果:数组元素为java.lang.Long类型

在JDK内置Nashorn中,第一条语句的结果是Integer类型,可正常调用要求List<Integer>的后端方法;但OpenJDK Nashorn中转为List<Double>,导致方法调用失败。仅在向空数组push Long类型时会触发该转换,其他场景类型均正常保留。

原因分析

这是OpenJDK Nashorn的特性而非bug:

  • 空数组初始化时没有任何类型上下文,OpenJDK Nashorn会默认将其视为JS原生数组。当第一次push Java数值包装类(如Long)时,会自动转为JS原生的Number类型,而JS Number在Java层面对应java.lang.Double。
  • 直接用元素初始化数组时,Nashorn能从初始元素推断出数组的类型上下文,会保留原Java包装类的类型,不会进行自动转换。

解决方案

需要修改代码来规避自动类型转换,可选方案如下:

1. 避免使用空数组初始化

直接用第一个元素初始化数组,后续push的元素会自动沿用该类型:

var testArray = [new java.lang.Long(1234)];
testArray.push(new java.lang.Long(5678));
// 所有元素均为java.lang.Long类型

2. push时显式保留Java类型

在push时重新包装元素,确保类型不被转换:

var testArray = [];
testArray.push(java.lang.Long.valueOf(1234));
// 或对已有Long对象重新包装
var longObj = new java.lang.Long(1234);
testArray.push(java.lang.Long.valueOf(longObj.longValue()));

3. 使用Java集合替代JS数组

如果需要严格的类型控制,直接使用Java的集合类,明确指定元素类型:

var testList = new java.util.ArrayList(java.lang.Long.class);
testList.add(new java.lang.Long(1234));
// 集合元素类型始终为java.lang.Long

测试用例验证

以下是完整测试用例,可复现该问题并验证解决方案:

var t1numberOne = java.lang.Long.valueOf('123');
var t1numberTwo = java.lang.Integer.valueOf('123');
var t1numberThree = java.lang.Double.valueOf('123');

print('No modification - int')
print("One: {} - {}", t1numberOne.getClass(), t1numberOne);
print("Two: {} - {}", t1numberTwo.getClass(), t1numberTwo);
print("Three: {} - {}", t1numberThree.getClass(), t1numberThree);
print('-----------------------------------------------------');

var t2numberOne = java.lang.Long.valueOf('123');
var t2numberTwo = java.lang.Integer.valueOf('123');
var t2numberThree = java.lang.Double.valueOf('123.7');

print('No modification - double')
print("One: {} - {}", t2numberOne.getClass(), t2numberOne);
print("Two: {} - {}", t2numberTwo.getClass(), t2numberTwo);
print("Three: {} - {}", t2numberThree.getClass(), t2numberThree);
print('-----------------------------------------------------');

var t3numberOne = java.lang.Long.valueOf('123');
var t3numberTwo = java.lang.Integer.valueOf('123');
var t3numberThree = java.lang.Double.valueOf('123');

var t3testArray = [t3numberOne, t3numberTwo, t3numberThree];

print('Adding to array - int!')
print("One: {} - {}", t3testArray[0].getClass(), t3testArray[0]);
print("Two: {} - {}", t3testArray[1].getClass(), t3testArray[1]);
print("Three: {} - {}", t3testArray[2].getClass(), t3testArray[2]);
print('-----------------------------------------------------');

var t4numberOne = java.lang.Long.valueOf('123');
var t4numberTwo = java.lang.Integer.valueOf('123');
var t4numberThree = java.lang.Double.valueOf('123.7');

var t4testArray = [t4numberOne.longValue(), t4numberTwo.intValue(), t4numberThree.doubleValue()];

print('Adding to array - double!')
print("One: {} - {}", t4testArray[0].getClass(), t4testArray[0]);
print("Two: {} - {}", t4testArray[1].getClass(), t4testArray[1]);
print("Three: {} - {}", t4testArray[2].getClass(), t4testArray[2]);
print('-----------------------------------------------------');

var t5testArray = [];
t4testArray.forEach(function(entry){
    t5testArray.push(entry);
})

print('Copying Long elements from other long array using .push()')
print("One: {} - {}", t5testArray[0].getClass(), t5testArray[0]);
print("Two: {} - {}", t5testArray[1].getClass(), t5testArray[1]);
print("Three: {} - {}", t5testArray[2].getClass(), t5testArray[2]);
print('-----------------------------------------------------');

var t6NumberOne = java.lang.Long.valueOf('123');
var t6NumberTwo = java.lang.Long.valueOf('456');
var t6NumberThree = java.lang.Long.valueOf('789');
var t6testArray = [t6NumberOne, t6NumberTwo, t6NumberThree];
var t6testCopyArray = [];
t6testArray.forEach(function(entry){
    t6testCopyArray.push(entry);
})

print('Copying Long elements from other long array using .push()')
print("One Original: {} - {}", t6testArray[0].getClass(), t6testArray[0]);
print("Two Original: {} - {}", t6testArray[1].getClass(), t6testArray[1]);
print("Three Original: {} - {}", t6testArray[2].getClass(), t6testArray[2]);
print('--')
print("One Copied: {} - {}", t6testCopyArray[0].getClass(), t6testCopyArray[0]);
print("Two Copied: {} - {}", t6testCopyArray[1].getClass(), t6testCopyArray[1]);
print("Three Copied: {} - {}", t6testCopyArray[2].getClass(), t6testCopyArray[2]);
print('-----------------------------------------------------');

var t7NumberOne = java.lang.Long.valueOf('123');
var t7NumberTwo = java.lang.Long.valueOf('456');
var t7NumberThree = java.lang.Long.valueOf('789');
var t7testArray = [t7NumberOne, t7NumberTwo, t7NumberThree];
var t7testCopyArray = [];
t7testArray.forEach(function(entry){
    t7testCopyArray.push(java.lang.Long.valueOf(entry));
})

print('Copying from other long array - converting to long during .push() (t7testCopyArray.push(java.lang.Long.valueOf(entry))')
print("One Original: {} - {}", t7testArray[0].getClass(), t7testArray[0]);
print("Two Original: {} - {}", t7testArray[1].getClass(), t7testArray[1]);
print("Three Original: {} - {}", t7testArray[2].getClass(), t7testArray[2]);
print('--')
print("One Copied: {} - {}", t7testCopyArray[0].getClass(), t7testCopyArray[0]);
print("Two Copied: {} - {}", t7testCopyArray[1].getClass(), t7testCopyArray[1]);
print("Three Copied: {} - {}", t7testCopyArray[2].getClass(), t7testCopyArray[2]);
print('-----------------------------------------------------');

var t8NumberOne = java.lang.Long.valueOf('123');
var t8NumberTwo = java.lang.Long.valueOf('456');
var t8NumberThree = java.lang.Long.valueOf('789');
var t8testArray = [t8NumberOne, t8NumberTwo, t8NumberThree];
var t8testCopyArray = [];
t8testCopyArray.push(t8NumberOne);
t8testCopyArray.push(t8NumberTwo);
t8testCopyArray.push(t8NumberThree);

print('Pushing Long elements into empty array using .push()')
print("One Original: {} - {}", t8testArray[0].getClass(), t8testArray[0]);
print("Two Original: {} - {}", t8testArray[1].getClass(), t8testArray[1]);
print("Three Original: {} - {}", t8testArray[2].getClass(), t8testArray[2]);
print('--')
print("One Copied: {} - {}", t8testCopyArray[0].getClass(), t8testCopyArray[0]);
print("Two Copied: {} - {}", t8testCopyArray[1].getClass(), t8testCopyArray[1]);
print("Three Copied: {} - {}", t8testCopyArray[2].getClass(), t8testCopyArray[2]);
print('-----------------------------------------------------');

var t9NumberOne = java.lang.Integer.valueOf('123');
var t9NumberTwo = java.lang.Integer.valueOf('456');
var t9NumberThree = java.lang.Integer.valueOf('789');
var t9testArray = [t9NumberOne, t9NumberTwo, t9NumberThree];
var t9testCopyArray = [];
t9testCopyArray.push(t9NumberOne);
t9testCopyArray.push(t9NumberTwo);
t9testCopyArray.push(t9NumberThree);

print('Pushing Integer elements into empty array using .push()')
print("One Original: {} - {}", t9testArray[0].getClass(), t9testArray[0]);
print("Two Original: {} - {}", t9testArray[1].getClass(), t9testArray[1]);
print("Three Original: {} - {}", t9testArray[2].getClass(), t9testArray[2]);
print('--')
print("One Copied: {} - {}", t9testCopyArray[0].getClass(), t9testCopyArray[0]);
print("Two Copied: {} - {}", t9testCopyArray[1].getClass(), t9testCopyArray[1]);
print("Three Copied: {} - {}", t9testCopyArray[2].getClass(), t9testCopyArray[2]);
print('-----------------------------------------------------');

内容的提问来源于stack exchange,提问作者Florian Johannes Pössl

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 16:22:32