使用Nashorn迭代数组

时间:2017-06-29 19:10:52

标签: javascript java arrays nashorn

当使用java的内置javascript解释器时,为什么我可以使用Arrays.forEach()而不是本机数组迭代java List?我有以下测试代码

var ArrayList = Java.type('java.util.ArrayList');
var list = new ArrayList();
list.add('a');
list.add('b');
list.add('c');

var StringArray = Java.type("java.lang.String[]");
var array = new StringArray(3);
array[0] = "A";
array[1] = "B";
array[2] = "C";

list.forEach(function(v) { print(v); });
array.forEach(function(v) { print(v); });

我希望打印出来

  

a b c A B C

但我得到了

  

a b c

     

TypeError:[Ljava.lang.String; @ 644e4fbf没有这样的功能" forEach"在第14行

以下是有效的,但为什么不是array.forEach()?

for (var i=0; i<array.length; ++i)
  print(array[i]);

我遇到的问题是我的javascript代码想要调用返回String []的java函数的加载,并且我想处理生成的对象,好像是一个常规的javascript数组。是否有一种更简单的方法来解决这个问题,而不是在java中编写大量的包装器函数来将我的数组转换为ArrayList?

2 个答案:

答案 0 :(得分:4)

当您在Java列表上调用forEach时,您正在调用继承自Iterable的List的forEach方法。 Nashorn支持在需要@FunctionalInterface对象时传递脚本函数,因此您可以将函数作为Consumer参数的参数传递。 Java数组上没有这样的forEach Java方法,因此第二个forEach方法调用失败。

请注意,JavaScript Array.prototype。forEach的Nashorn实现是通用的。它也适用于Java数组,列表。我调整了脚本,将Array.prototype.forEach用于Java List和java String数组。

var ArrayList = Java.type('java.util.ArrayList');
var list = new ArrayList();
list.add('a');
list.add('b');
list.add('c');

var StringArray = Java.type("java.lang.String[]");
var array = new StringArray(3);
array[0] = "A";
array[1] = "B";
array[2] = "C";

var forEach = Array.prototype.forEach;

forEach.call(list, function(v) { print(v); });
forEach.call(array, function(v) { print(v); });

答案 1 :(得分:0)

感谢您的建议。它不仅仅是迭代数组,而且编写脚本的人可能希望调用Arrays.sort(),Arrays.filter()等函数。

最后,我决定更改所有Java函数,使它们返回一个真正的JavaScript数组,而不是本机Java数组,方法是通过一个辅助函数来调用Java.from():

private JSObject toJavascript(Object javaObject)
{
    String tmpkey = "tmp"+javaObject.hashCode()+System.currentTimeMillis();
    engine.put(tmpkey, javaObject);
    JSObject jsObject = (JSObject)engine.eval("Java.from("+tmpkey+")");
    engine.put(tmpkey, null);
    return jsObject;
}

可能有一个整洁的事情,但至少它似乎工作!