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

Java Nashorn create JS object in Java, when I have an object representing JS function

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

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

据我所知,如果我将它的实例作为 Java 对象,我将无法使用其他字段/方法,但如果它是 JavaScript 对象,我可以。那么如何使用 Java 代码将此 class 实例化为 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();
        }
    }

    ...

}

是的,使用 Java.extend,您只能覆盖超级 class 方法。您不能向生成的子 class.

添加新的 Java 字段或新的 java 方法

如果您的问题是关于如何从 java 代码中执行相当于 java 脚本函数的 JS "new",那么:

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 subclass 的实例,您可以定义将创建 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);
  }
}