2016-01-20 71 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