简体   繁体   English

使用Nashorn遍历数组

[英]Iterating over array with Nashorn

When using java's built-in javascript interpreter, why can I iterate over a java List using Arrays.forEach() but not over a native array? 使用Java的内置javascript解释器时,为什么我可以使用Arrays.forEach()遍历Java列表,而不能遍历本机数组? I have the following test code 我有以下测试代码

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); });

which I'd expect to print out 我希望将其打印出来

abc ABC abc ABC

but instead I get 但是我得到了

abc ABC

TypeError: [Ljava.lang.String;@644e4fbf has no such function "forEach" in at line number 14 TypeError:[Ljava.lang.String; @ 644e4fbf在第14行没有这样的函数“ forEach”

The following works, but why not array.forEach() ? 以下工作,但为什么不array.forEach()?

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

The issue I have is that my javascript code wants to call a load of java functions that return a String[], and I want to deal with the resulting object as if was a regular javascript array. 我遇到的问题是我的JavaScript代码想要调用返回String []的Java函数,而我希望像处理常规javascript数组那样处理结果对象。 Is there an easier way to fix this than writing loads of wrapper functions in java that convert my arrays to an ArrayList? 有没有比在Java中编写包装程序函数(将我的数组转换为ArrayList)更简单的方法来解决此问题?

When you call forEach on a Java List, you are invoking the List's forEach method inherited from Iterable . 在Java列表上调用forEach时,您正在调用从Iterable继承的List的forEach方法。 Nashorn supports passing a script function whenever a @FunctionalInterface object is expected and so you can pass function as argument for the Consumer parameter. Nashorn支持在需要@FunctionalInterface对象时传递脚本函数,因此您可以将函数作为Consumer参数的参数传递。 There is no such forEach Java method on Java arrays and hence the second forEach method call fails. Java数组上没有这样的forEach Java方法,因此第二次forEach方法调用失败。

Note that the Nashorn implementation of the JavaScript Array.prototype. 请注意,JavaScript Array.prototype的Nashorn实现。 forEach is generic. forEach是通用的。 It works on Java arrays, lists as well. 它也适用于Java数组和列表。 I adjusted your script to use Array.prototype.forEach for both Java List and java String array. 我将脚本调整为对Java List和Java String array使用Array.prototype.forEach。

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); });

Thanks for the suggestions. 感谢您的建议。 It's not just about iterating over the array but also that people writing scripts might expect to call functions like Arrays.sort(), Arrays.filter() etc. 这不仅涉及遍历数组,而且编写脚本的人们可能希望调用诸如Arrays.sort(),Arrays.filter()等函数。

In the end I decided to change all the Java functions so they return a true JavaScript array, rather than a native Java array, by passing them through a helper function to call Java.from(): 最后,我决定更改所有Java函数,以使它们通过帮助函数传递来调用Java.from(),从而返回真正的JavaScript数组,而不是本机Java数组:

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;
}

There's probably a neater to do this but at least it seems to work! 这样做可能更整洁,但至少看来可行!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM