我有一个Java数组,比如说,Object[]
,我需要传递给JS执行环境ScriptEngine
。
我不能简单地以下列方式将其作为财产:
ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
Object[] array = {1, 2, 3};
engine.put("prop", array);
因为在JS环境中,表达式Array.isArray(prop)
将被评估为false
,而我需要它true
。
jdk.nashorn.internal.objects.NativeArray
构造函数已关闭,这意味着您无法显式实例化NativeArray
。
但是,可以使用jdk.nashorn.internal.objects.Global.instance().wrapAsObject
将Java数组Object[]
转换为NativeArray
,并将结果对象识别为JS数组,即Array.isArray
将返回对于这个对象是真的。
虽然这给出了期望的结果,但使用internal
包中的类并不是一个好主意,如果你使用的是Java 9,那就更糟了。
因此,我想知道,有没有更好的方法为JS执行环境提供Java对象,假设我无法更改JS源,以便该对象被识别为真正的JS数组,即Array.isArray
返回true?
答案 0 :(得分:1)
您可以通过javascript创建本机数组,然后将相应的ScriptObjectMirror
转换为List<Object>
,看起来该列表将使用本机数组作为底层存储:
ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
ScriptObjectMirror jsArray = (ScriptObjectMirror) engine.eval("var arr = []; arr");
@SuppressWarnings("unchecked")
List<Object> ls = jsArray.to(List.class);
ls.add(1);
ls.add(2);
ls.add(3);
System.out.println(ls); // [1, 2, 3]
engine.eval("print(arr)"); // 1,2,3
engine.eval("print(Array.isArray(arr))"); // true
然后,您可以在Java端使用此列表。
答案 1 :(得分:1)
Nashorn有一个非标准的顶级Java
对象,其中包括名为to
和from
的有用转换方法。如果你有一个Java数组arr
,那么Java.from(arr)
将创建一个JS数组作为Java数组的浅表副本。它也适用于任何java.util.Collection
。
请注意,在大多数情况下,您可以在Nashorn中本地使用Java数组和列表;如果由于某种原因你需要一个真正的JavaScript原生数组(例如使用数组推导函数),你会想要使用这个方法。