【问题标题】:Java Nashorn engine ArrayNode handlingJava Nashorn 引擎 ArrayNode 处理
【发布时间】:2018-04-18 12:14:10
【问题描述】:

我使用 Java Nashorn 引擎 来执行 Javascript 代码。我使用ScriptEngine objecteval 方法,该方法具有“绑定”的第二个参数。我用它来将变量传递给引擎。它适用于 Object 类型和原始包装类,但是当我尝试传递 ArrayNode 时,它​​不能作为 JavaScript 数组工作,我不知道为什么。

示例代码:

String scriptText = "myarray[1] = 666";
ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
Bindings bindings = engine.createBindings();
ArrayNode arrayNode = mapper.createArrayNode();
array.add(1);
array.add(2);
array.add(3);

bindings.put("myarray", arrayNode);
engine.eval(scriptText, bindings);

这应该会更改绑定对象中的 myarray 值,但不会。

我做错了什么?

【问题讨论】:

    标签: java nashorn


    【解决方案1】:

    Nashorn 支持类似脚本数组的索引访问/更新

    1. Java 数组对象
    2. java.util.ArrayList 对象
    3. jdk.nashorn.api.scripting.JSObject 对象

    如果 ArrayNode 不是 ArrayList 子类型,您可以在 ArrayNode 类中实现 JSObject 接口,或者用 JSObject 实现包装 ArrayNode 并将其公开给脚本 (https://docs.oracle.com/javase/8/docs/jdk/api/nashorn/jdk/nashorn/api/scripting/JSObject.html)。

    举例说明上述三种情况:

    import java.util.*;
    import javax.script.*;
    import jdk.nashorn.api.scripting.*;
    
    public class Main {
      public static void main(String[] args) throws Exception {
        ScriptEngineManager m = new ScriptEngineManager();
        ScriptEngine e = m.getEngineByName("nashorn");
    
        // Java array accessed by indexing
        String[] arr = { "hello", "world" };
        e.put("jarr", arr);
        e.eval("jarr[1] = jarr[1].toUpperCase()"); // change first element
        System.out.println(arr[1]); // change reflected here
    
        // Java ArrayList accessed by indexing
        ArrayList<String> alist = new ArrayList<>();
        alist.add("nashorn");
        alist.add("javascript");
        e.put("jlist", alist);
        e.eval("jlist[0] = 'Nashorn'");
        System.out.println(alist.get(1)); // change reflected here
    
        // Third case - a JSObject array-like object accessed by indexing
        e.put("myObj", new AbstractJSObject() {
            private Map<Integer, Object> values = new HashMap<>();
            @Override
            public void setSlot(int index, Object val) {
                values.put(index, val);
            }
    
            @Override
            public Object getSlot(int index) {
                return values.get(index);
            }
       });
    
       e.eval("myObj[0] = 'hello'");
       e.eval("print(myObj[0])");
     }
    }
    

    【讨论】:

    • 哇!这是一个惊人的答案!谢谢 :) 像魅力一样工作 :)
    猜你喜欢
    • 2018-09-19
    • 2018-11-30
    • 1970-01-01
    • 2014-08-19
    • 2015-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-09
    相关资源
    最近更新 更多