当我有一个表示JS函数的对象时,Java Nashorn在Java中创建JS对象

时间:2016-07-07 09:04:47

标签: javascript java nashorn

我有一个基类,它以Entity作为构造函数参数。我在JavaScript中扩展了这个基类,它看起来像这样:

Java.extend(BaseClass, {
       someAbstractMethod : function() { ... },
       someAdditionalField : ...,
       etc
})

据我所知,如果我将它的实例作为Java对象,我就不能使用其他字段/方法,但如果它是一个JavaScript对象,我可以。那么如何使用Java代码将此类实例化为JS对象?

public class ScriptedEntity extends Entity implements Scripted<EntityScriptFunctions> {

    private CompiledScript script;
    private Object implemented_script_class;
    private Object my_script_instance;
    private Invocable invocable;

    public ScriptedEntity(float x, float y, CompiledScript script) {
        super(x, y);
        invocable = (Invocable) script.getEngine();
        try {
            implemented_script_class = script.eval();
            my_script_instance = invocable.invokeFunction("???", this); //'this' is the constructor argument
        } catch (ScriptException | IllegalArgumentException | NoSuchMethodException | SecurityException e) {
            e.printStackTrace();
        }
    }

    ...

}

1 个答案:

答案 0 :(得分:2)

是的,使用Java.extend,您只能覆盖超类方法。您不能向生成的子类添加新的Java字段或新的java方法。

如果你的问题是关于如何做相当于JS&#34; new&#34;从java代码中获取javascript函数,然后:

import javax.script.*;
import jdk.nashorn.api.scripting.*;

public class Main {
  public static void main(String[] args) throws Exception {
    ScriptEngineManager m = new ScriptEngineManager();
    ScriptEngine e = m.getEngineByName("nashorn");
    e.eval("function Point(x, y) { this.x = x; this.y  = y}");
    JSObject pointFunc = (JSObject)e.get("Point");
    JSObject pointObj =  (JSObject)pointFunc.newObject(43, 55);
    System.out.println(pointFunc.isInstance(pointObj));
    System.out.println(pointObj.getMember("x"));
    System.out.println(pointObj.getMember("y"));
  }
}

另请参阅:https://docs.oracle.com/javase/8/docs/jdk/api/nashorn/jdk/nashorn/api/scripting/JSObject.html

要创建使用Java.extend定义的Java子类的实例,您可以定义将创建Java对象的脚本函数。您可以通过Invocable.invokeFunction或JSObject.call从java代码调用该函数。

import java.util.*;
import javax.script.*;
import jdk.nashorn.api.scripting.*;

public class Main {
  public static void main(String[] args) throws Exception {
    ScriptEngineManager m = new ScriptEngineManager();
    ScriptEngine e = m.getEngineByName("nashorn");
    e.eval("var MyHashMap = Java.extend(java.util.HashMap, {})");
    e.eval("function createMyHashMap() { return new MyHashMap(); }");
    HashMap hm = (HashMap) ((Invocable)e).invokeFunction("createMyHashMap");
    System.out.println(hm);
  }
}