Nashorn将Java函数分配给地图

时间:2015-09-17 15:12:08

标签: javascript java java-8 nashorn

我有这个引擎运行用户输入(可信)的javascript函数,使用Nashorn为它们过滤一些数据。不想详细了解要求,但让我们说它是某种插件系统。

这个javascript获取一个Java地图(其作用类似于JS对象)作为获取一些上下文数据的参数。 所以我想为这个JS对象添加一些方便的扩展方法给用户。所以我做了以下事情:

Map<String, String> inputMap = ....
inputMap.put("containsMagic", (Function<String, Boolean>) param -> some complex magic check and return boolean);

完美无缺!

if(inputMap.containsMagic('Im Por Ylem'))
  do stuff;

但是,我希望它也不接受任何参数,因为null是有效值,containsMagic()看起来比containsMagic(null)好。

if(inputMap.containsMagic())
  do stuff;

但我明白了:

TypeError: Can not invoke method ......$$Lambda$15/1932831450@30c15d8b with the passed arguments; they do not match any of its method signatures.

考虑到Java的运作方式,我认为这是正常的。如果我通过null,它当然有效,但这不是很直观。

我无法添加另一个带有0个参数和相同名称的函数,因为Java映射是单键控制的。 复杂魔法检查需要在java中,所以我也不能分配javascript函数(JSObject?)。我有什么想法可以做到这一点吗?

2 个答案:

答案 0 :(得分:1)

您可以使用varargs参数将containsMagic实现为显式方法:

public static class InputMap extends HashMap<String, Object> {
    public Boolean containsMagic(String... args) {
        String arg = args.length == 1 ? args[0] : null;
        // do magic 
    }
}

...
Map<String, Object> inputMap = new InputMap(); 

答案 1 :(得分:1)

遗憾的是,

java.util.function缺少可变参数函数的标准接口,但您可以自己添加:

@FunctionalInterface
public interface VariadicFunction<T,R> {
    public R apply(T... args);
}

然后

inputMap.put("containsMagic", (VariadicFunction<String, Boolean>) param -> some complex magic check and return boolean);