Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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? 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

a b c A B C

but instead I get

a b c

TypeError: [Ljava.lang.String;@644e4fbf has no such function "forEach" in at line number 14

The following works, but why not 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. Is there an easier way to fix this than writing loads of wrapper functions in java that convert my arrays to an ArrayList?

like image 329
Rolf Avatar asked Sep 18 '25 23:09

Rolf


1 Answers

When you call forEach on a Java List, you are invoking the List's forEach method inherited from Iterable. Nashorn supports passing a script function whenever a @FunctionalInterface object is expected and so you can pass function as argument for the Consumer parameter. There is no such forEach Java method on Java arrays and hence the second forEach method call fails.

Note that the Nashorn implementation of the JavaScript Array.prototype.forEach is generic. It works on Java arrays, lists as well. I adjusted your script to use Array.prototype.forEach for both Java List and java String array.

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); });
like image 188
A. Sundararajan Avatar answered Sep 21 '25 12:09

A. Sundararajan