How can I pass a proper method reference in so Nashorn can execute it?

只谈情不闲聊 提交于 2019-12-04 18:05:28

JSObject.getMember can return any script "callable". That could be another JSObject that returns 'true' for isFunction or a Java functional interface object. Couple of simple Java sample programs here:

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

public class Main {
    public static void main(String[] args) throws Exception {
        ScriptEngineManager m = new ScriptEngineManager();
        ScriptEngine e = m.getEngineByName("nashorn");

        // The following JSObject wraps this list
        List<String> l = new ArrayList();
        l.add("hello");
        l.add("world");

        JSObject jsObj = new AbstractJSObject() {
            @Override
            public Object getMember(String name) {
                // return a "function" object for "map"
                if (name.equals("map")) {
                    return new AbstractJSObject() {
                        @Override
                        public Object call(Object thiz, Object... args) {
                            // first argument is the callback passed from script
                            JSObject callable = (JSObject)args[0];
                            List<Object> res = new ArrayList<>();
                            for (Object obj : l) {
                                // call callback on each object and add the result to new list
                                res.add(callable.call(null, obj));
                            }

                            // return fresh list as result of map (or this could be another wrapper)
                            return res;
                        }

                        @Override
                        public boolean isFunction() { return true; }
                    };
                } else {
                    // unknown property
                    return null;
                }
           }
        };

        e.put("obj", jsObj);
        // map each String to it's uppercase and print result of map
        e.eval("print(obj.map(function(x) x.toUpperCase()))");
    }
}

The above example returns a callable JSObject for "map" property. The returned "function" itself uses a callback function as argument. All script functions (and objects) are passed as JSObjects to Java code and so 'map' code casts first argument to JSObject to invoke the script callback function.

The above sample modified to use a functional interface is as follows:

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

public class Main2 {
    public static void main(String[] args) throws Exception {
        ScriptEngineManager m = new ScriptEngineManager();
        ScriptEngine e = m.getEngineByName("nashorn");

        // The following JSObject wraps this list
        List<String> l = new ArrayList();
        l.add("hello");
        l.add("world");

        JSObject jsObj = new AbstractJSObject() {
            @Override
            public Object getMember(String name) {
                if (name.equals("map")) {
                    // return a functional interface object - nashorn will treat it like
                    // script function!
                    return (Function<JSObject, Object>)callback -> {
                        List<Object> res = new ArrayList<>();
                        for (Object obj : l) {
                            // call callback on each object and add the result to new list
                            res.add(callback.call(null, obj));
                        }

                        // return fresh list as result of map (or this could be another wrapper)
                        return res;
                    };
                } else {
                    // unknown property
                    return null;
                }
           }
        };

        e.put("obj", jsObj);
        // map each String to it's uppercase and print result of map
        e.eval("print(obj.map(function(x) x.toUpperCase()))");
    }
}

Hope the above samples will help you in coming up with Kotlin version for your scenario.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!