Java / Nashorn 在绑定/全局范围内放置一个函数

Java / Nashorn put one function in binding / global scope

我有一个静态方法,例如:

some abstract class C {
    void dump( Object o ) {
}

我想将其传递给 js,以便我可以在全局范围内直接使用它,例如:

js> dump( new Something() );

到目前为止我找到的唯一方法是创建一个像

这样的实例
public class CStub {
    void dump( Object o ){ C.dump( o ); }
}

通过以下方式将其放入 nashorn:

engine.put( "stub", new CStub() );

然后在 js 中:

js> var dump = stub.dump

但是是否有另一种不涉及存根创建并将方法直接放在全局范围内的方法?

您可以在 class 中实现功能接口 (https://docs.oracle.com/javase/8/docs/api/java/lang/FunctionalInterface.html),例如 java.util.function.Function,并将其对象作为全局变量公开给 nashorn。 Nashorn 将任何 "functional interface" 对象视为函数并允许直接调用它。 公开一个 "dump" 函数的简单示例如下:

import javax.script.*;
import java.util.function.Function;

public class Main {
   // a Function implementation
   private static class MyFunc implements Function<String, Void> {
       @Override
       public Void apply(String msg) {
           System.out.println(msg);
           return null;
       }
   }

   public static void main(String[] args) throws Exception {
       ScriptEngineManager m = new ScriptEngineManager();
       ScriptEngine e = m.getEngineByName("nashorn");

       // expose functional interface object as a global var
       e.put("dump", new MyFunc());

       // invoke functional interface object like a function!
       e.eval("dump('hello')");
   }
}

甚至更短,您可以采用方法引用 (C::dump),将其转换为适当的功能接口(在您的情况下 Consumer 很好,因为它接收单个参数并且 returns void), 并放入全局作用域

import javax.script.*;
import java.util.function.Consumer;

public class Main {
    public static void main(String[] args) throws Exception {
        ScriptEngineManager m = new ScriptEngineManager();
        ScriptEngine e = m.getEngineByName("nashorn");

        // expose method-reference-as-function-object as a global var
        e.put("dump", (Consumer<Object>)C::dump);

        // invoke functional interface object like a function!
        e.eval("dump('hello')");
    }
}