2017-06-29 90 views
2

当使用java的内置JavaScript解释器时,为什么我可以使用Arrays.forEach()遍历java列表,但不能遍历本地数组?我有以下的测试代码使用Nashorn对阵列进行迭代

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 has no such function "forEach" in at line number 14

下面的作品,但为什么不array.forEach( )?

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

我的问题是,我的javascript代码要调用Java函数返回一个String []的负荷,我想处理由此产生的对象,就好像是一个普通的JavaScript数组。有没有更容易的方法来解决这个问题,而不是编写大量的包装函数在java中将我的数组转换为ArrayList?

+0

您可以使用(非常不幸,在我看来)Nashorn'为每个(var元素数组)'语法。 (从Mozilla的扩展中,我认为已经在现代Firefox中被淘汰了。) – Pointy

回答

3

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

请注意,JavaScript Array.prototype的Nashorn实现。 forEach是通用的。它也适用于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); }); 
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; 
} 

有可能是一个更简洁的做到这一点,但至少它似乎工作!