2017-04-12 144 views
1

Java的子類調用函數我有一個JavaScript腳本,看起來像這樣:在犀牛

function run(database) { 
    var result = database.query("query", "some resource name"); 
    //operations on result 
    return result; 
} 

,我有Java代碼執行的腳本是這樣的:

public Object execute(String script, Database database) { 
    NashornScriptEngineFactory nsef = new NashornScriptEngineFactory(); 
    ScriptEngine engine = nsef.getScriptEngine(); 
    try { 
     engine.eval(script); 
     Invocable invocable = (Invocable) engine; 
     return invocable.invokeFunction("run", database); 
    } catch(ScriptException e) { 
     throw new RuntimeException(e); 
    } 
} 

Database是一個包含幾個方法定義的接口,但是而不是包含query方法。我打電話execute,執行Database,稱之爲DatabaseImpl確實query方法。這將是多態的,並且該腳本需要知道傳遞給它的Database實例上有哪些方法可用。我決定不要使用這種泛型,因爲它們在運行時被擦除,所以JavaScript無法使用它們,因此腳本編寫者需要正確地使用這些類型。

然而,當運行此代碼時,得到以下異常:

javax.script.ScriptException: TypeError: database.query is not a function in <eval> at line number 25 

基本上,要點是,我有它實現一個接口的對象,並調用該特定實例可實現的方法,但不是接口定義的一部分。我的印象是,這應該仍然有效,但事實並非如此。對我而言,我需要在腳本中進行子播以訪問query方法(這甚至有可能嗎?),爲什麼我會得到這個錯誤?是否因爲該方法不能從接口定義中獲得?有沒有解決方法?

謝謝。

回答

1

這是主要的類:

package so; 
import java.io.InputStreamReader; 
import javax.script.Invocable; 
import javax.script.ScriptEngine; 
import javax.script.ScriptEngineManager; 

public class Nashorn { 
    public static void main(String[] args) { 
     try (InputStreamReader in = resource()) { 
      ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn"); 
      engine.eval(in); 
      Invocable invocable = (Invocable) engine; 
      Database database = new DatabaseImpl(); 
      Object x = invocable.invokeFunction("run", database); 
      System.out.println(x); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    private static InputStreamReader resource() throws Exception { 
     return new InputStreamReader(Nashorn.class.getResourceAsStream("db.js"), "utf-8"); 
    } 

} 

接口和實現

package so; 

public interface Database { 
    void connect(); 
} 

package so; 

import java.util.ArrayList; 
import java.util.Arrays; 
import java.util.List; 

public class DatabaseImpl implements Database { 

    @Override 
    public void connect() { 
     System.out.println("Connecting"); 
    } 

    public List<?> query(String ... stmt){ 
     List<String> lst = new ArrayList<>(); 
     lst.addAll(Arrays.asList(stmt)); 
     lst.addAll(Arrays.asList("A","B","C")); 
     return lst; 
    } 

} 

JavaScript文件(以便/ db.js)

function run(database) { 
    var result = database.query("query", "some resource name"); 
    //operations on result 
    return result; 
} 

運行結果在:

[query, some resource name, A, B, C] 

它基本上工作。

+0

可能PEBCAC然後...我會繼續尋找。感謝您檢查了這一點。 – Peter