2016-01-20 73 views
1

我有一个静态方法,如:的Java /犀牛把一个函数绑定/全球范围内

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

我想它传递给,我可以直接使用它在全球范围内像JS:

js> dump(new Something()); 

到目前为止,我发现的唯一办法是创造一个像

public class CStub { 
    void dump(Object o){ C.dump(o); } 
} 

把它放在一个实例通过犀牛:

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

,然后在JS:

js> var dump = stub.dump 

但有另一种方法来这里面不涉及存根创建,并直接在全球范围内提出的方法是什么?

回答

6

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

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')"); 
    } 
} 
+0

嘿,非常感谢!有用。虽然有些奇怪。 – Scheintod

2

更短,您可以采取的方法引用(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')"); 
    } 
} 
+0

这正是我最后所做的。出乎意料的是,来自java方面的方法签名与使用实例时稍有不同。 – Scheintod