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

时间:2016-01-20 19:30:34

标签: java scope nashorn

我有一个静态方法,如:

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

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

2 个答案:

答案 0 :(得分:7)

您可以在类中实现类似java.util.function.Function的函数接口(https://docs.oracle.com/javase/8/docs/api/java/lang/FunctionalInterface.html),并将其对象作为全局变量公开给nashorn。 Nashorn对待任何"功能界面"对象作为一个函数,允许直接调用它。 公开" 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')");
   }
}

答案 1 :(得分:3)

更短,您可以采用方法引用(C::dump),将其转换为适当的功能接口(在您的情况下Consumer很好,因为它接收单个参数并返回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')");
    }
}