2017-06-29 10 views
2

javaの組み込みのJavaScriptインタープリタを使用すると、なぜArrays.forEach()を使用してJavaリストを反復処理できますが、ネイティブ配列では処理できませんか?私は、次のテストコードNashornで配列を反復する

私は

a b c A B C

をプリントアウトすることを期待したい

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

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関数の負荷を呼び出すために望んでいることである、と私は定期的なjavascript配列であるかのように結果のオブジェクトに対処したいと思います。配列をArrayListに変換するJavaのラッパー関数のロードを記述するより簡単な方法がありますか?

+0

Nashorn '(配列内のvar要素)構文の(非常に不幸なことに、私の意見では)'を使うことができます。 (最近のFirefoxでは、Mozillaの拡張機能を利用していると思います。 – Pointy

答えて

3

forEachをJava Listで呼び出すと、Iterableから継承されたListのforEachメソッドが呼び出されます。 Nashornは、@FunctionalInterfaceオブジェクトが必要となるたびにスクリプト関数を渡すことをサポートしているため、Consumerパラメータの引数として関数を渡すことができます。このようなforEach JavaメソッドはJava配列には存在しないため、2番目のforEachメソッド呼び出しは失敗します。

JavaScript Array.prototypeのNashornの実装に注意してください。 forEachは一般的です。これはJava配列、リストでも機能します。私はあなたのスクリプトを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); }); 
0

ありがとうございます。配列を反復するだけでなく、スクリプトを書く人々がArrays.sort()、Arrays.filter()などの関数を呼び出すことが期待されるかもしれません。

最後にすべてのJava関数を変更することにしました。 Java.from()を呼び出すためにヘルパー関数を介してそれらを渡すことによって、むしろネイティブJava配列よりも、真のJavaScriptの配列を返す:あり、おそらくこれを行うには滑らかな印象だが、少なくとも動作しているようです

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