如何在不使用 "internal" 子包中的 类 的情况下包装到 Nashorn 中的 NativeArray
How to wrap to NativeArray in Nashorn without using classes from "internal" subpackage
我有一个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
对于此对象 return 为真。
虽然这给出了预期的结果,但使用 internal
包中的 类 并不是一个好主意,如果你使用 Java 9.[=26 则更糟=]
因此,我想知道,假设我无法更改 JS 源,是否有更好的方法向 JS 执行环境提供 Java 对象,以便该对象被识别为真正的 JS 数组,即 Array.isArray
return是真的吗?
可以通过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 端使用此列表。
Nashorn 有一个非标准的顶级 Java
对象,其中包含名为 to
和 from
的有用转换方法。如果你有一个 Java 数组 arr
,那么 Java.from(arr)
将创建一个 JS 数组作为 Java 数组的浅表副本。它也适用于任何 java.util.Collection
.
请注意,在大多数情况下,您可以在 Nashorn 中原生使用 Java 数组和列表;如果出于某种原因您需要一个实际的 JavaScript 本机数组(例如,使用数组推导函数),您将需要使用此方法。
我有一个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
对于此对象 return 为真。
虽然这给出了预期的结果,但使用 internal
包中的 类 并不是一个好主意,如果你使用 Java 9.[=26 则更糟=]
因此,我想知道,假设我无法更改 JS 源,是否有更好的方法向 JS 执行环境提供 Java 对象,以便该对象被识别为真正的 JS 数组,即 Array.isArray
return是真的吗?
可以通过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 端使用此列表。
Nashorn 有一个非标准的顶级 Java
对象,其中包含名为 to
和 from
的有用转换方法。如果你有一个 Java 数组 arr
,那么 Java.from(arr)
将创建一个 JS 数组作为 Java 数组的浅表副本。它也适用于任何 java.util.Collection
.
请注意,在大多数情况下,您可以在 Nashorn 中原生使用 Java 数组和列表;如果出于某种原因您需要一个实际的 JavaScript 本机数组(例如,使用数组推导函数),您将需要使用此方法。