Java和Javascript绑定函数,将数组作为参数

时间:2018-10-24 13:45:04

标签: javascript java scriptengine

我正在努力实现以下目标。 Java应用程序应该通过ScriptEngineManager / ScriptEngine运行javascript,并且javascript应该能够调用Java应用程序中的函数。只要只有一个简单的变量往返传递就可以了。但是我不能让它通过数组。 这是我的代码:

private static class test implements Function<Integer[], Integer[]> {
    @Override
    public Integer[] apply(Integer[] msg) {
        for(int i = 0; i < msg.length; i++) System.out.println(msg[i]);     
        Integer[] a = {1, 2, 3};           
        return a;
    }
}

public static void main(String[] args) throws ScriptException {
    String ps = "var e = [0x04, 0x05, 0x06]; var a = send(e); for(i in a) print(i);";
    ScriptEngineManager sm = new ScriptEngineManager();
    ScriptEngine eng = sm.getEngineByName("JavaScript");
    Bindings mbind = eng.createBindings();
    mbind.put("send", new test());
    eng.setBindings(mbind, ScriptContext.ENGINE_SCOPE);
    Object t = eng.eval(ps);
}

我得到了错误:

  

线程“主”中的异常java.lang.ClassCastException:jdk.nashorn.api.scripting.ScriptObjectMirror无法转换为[Ljava.lang.Integer;       在scripttest $ test.apply(scripttest.java:1)       在jdk.nashorn.internal.scripts.Script $ \ ^ eval_.:program(:1)       在jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:637)       在jdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:494)       在jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:393)       在jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:446)       在jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:403)       在jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:399)       在jdk.nashorn.api.scripting.NashornScriptEngine.eval(NashornScriptEngine.java:155)       在javax.script.AbstractScriptEngine.eval处(未知源)       在scripttest.main(scripttest.java:26)

有人知道如何传递数组吗?

谢谢! 问候

1 个答案:

答案 0 :(得分:0)

在Java中(在原始类型以及所有垃圾方面),对数组的反射有点问题,因此JSR-223脚本引擎遇到了麻烦。我已经使用新的GraalVM尝试了相同的代码,并且遇到了相同的问题-引擎放弃了寻找良好的映射,而只是尝试提交其数组值的本机表示(Nashorn使用ScriptObjectMirror,而GraalVM使用PolyglotMap)。

如果您希望宿主函数看起来像是在接受“真实数组”(来宾数组的实现),则宿主函数将需要接受基础ScriptEngine的内部实现并学习操作在那。根据{{​​3}}和this SO answer,您应该能够使用obj.to(int[].class)方法从代理对象中提取内部整数数组。

此方法的主要缺点是您的宿主函数必须支持您可能希望支持的每个特定ScriptEngine的每个内部表示形式。

由于当前的JDK中不推荐使用Nashorn Javascript引擎,因此您可能还希望支持GraalVM,在这种情况下,您的实现可能看起来像这样:

private static class test implements Function<Object, Integer[]> {
    @Override
    public Integer[] apply(Object inp) {
        int[] msg;
        if (inp instanceof ScriptObjectMirror)
            msg = ((ScriptObjectMirror)inp).to(int[].class);
        else if (inp instanceof AbstractMap)
            msg = Value.asValue(inp).as(int[].class);
        else
            return null;
        for (int i = 0; i < msg.length; i++)
            System.out.println(msg[i]);
        Integer[] a = { 1, 2, 3 };
        return a;
    }
}