web-dev-qa-db-ja.com

配列がIterableに割り当てられないのはなぜですか?

java5では、次のように記述できます。

Foo[] foos = ...
for (Foo foo : foos) 

または、forループでIterableを使用します。これは非常に便利です。

ただし、次のように反復可能の汎用メソッドを記述することはできません。

public void bar(Iterable<Foo> foos) { .. }

iterableではないため、配列を使用して呼び出します。

Foo[] foos = { .. };
bar(foos);  // compile time error 

この設計決定の背後にある理由について疑問に思っています。

174
dfa

配列はインターフェース(CloneableおよびJava.io.Serializable)。では、なぜIterableではないのでしょうか? Iterableiteratorメソッドを強制的に追加し、配列はメソッドを実装しないと思います。 char[]toStringもオーバーライドしません。とにかく、参照の配列は理想的ではないと考えるべきです-Listsを使用してください。 dfaのコメントとして、Arrays.asListは、明示的に変換を行います。

(そうは言っても、配列でcloneを呼び出すことができます。)

72

配列はオブジェクトですが、そのアイテムはそうでない場合があります。配列は、Iterableが対応できないintのようなプリミティブ型を保持する場合があります。少なくともそれは私が考えるものです。

57
Gareth Adamson

配列はIterableをサポートする必要がありますが、.NET配列が位置による読み取り専用ランダムアクセスを許可するインターフェイスをサポートしないのと同じ理由で、サポートしません(そのようなインターフェイスは標準として定義されていません)。基本的に、フレームワークにはしばしば迷惑な小さなギャップがありますが、これを修正する時間はありません。最適な方法で修正できるかどうかは関係ありませんが、多くの場合、できません。

PDATE:公平を期すため、位置によるランダムアクセスをサポートするインターフェイスをサポートしていない.NETアレイについて説明しました(私のコメントも参照)。しかし、.NET 4.5では、正確なインターフェイスが定義されており、配列とList<T>クラスでサポートされています。

IReadOnlyList<int> a = new[] {1, 2, 3, 4};
IReadOnlyList<int> b = new List<int> { 1, 2, 3, 4 };

可変リストインターフェイスIList<T>IReadOnlyList<T>を継承しないため、すべてが完全ではありません。

IList<int> c = new List<int> { 1, 2, 3, 4 };
IReadOnlyList<int> d = c; // error

たぶん、このような変更には後方互換性の問題があるかもしれません。

Javaの新しいバージョンで同様のことが進展している場合、コメントで知りたいと思います! :)

16

残念ながら、配列は「class- enough」ではありません。 Iterableインターフェイスを実装していません。

配列はClonableとSerializableを実装するオブジェクトになりましたが、配列は通常の意味ではオブジェクトではありませんであり、インターフェイスを実装していません。

For-eachループでそれらを使用できる理由は、Sunが配列のシンタックスシュガーを追加したためです(特殊なケースです)。

配列はJava 1で 'ほとんどのオブジェクト'として始まったため、それらを変更するのはあまりにも劇的すぎるrealJavaのオブジェクト。

14
jjnguy