web-dev-qa-db-fra.com

Pourquoi un tableau n'est-il pas assignable à Iterable?

avec Java5 on peut écrire:

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

ou simplement en utilisant un Iterable dans la boucle for. C'est très pratique.

Cependant, vous ne pouvez pas écrire une méthode générique pour itérable comme ceci:

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

et en l'appelant avec un tableau puisqu'il ne s'agit pas d'un Iterable:

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

Je me demande quelles sont les raisons qui ont motivé cette décision de conception.

174
dfa

Les tableaux peuvent implémenter des interfaces (Cloneable et Java.io.Serializable). Alors pourquoi pas Iterable? J'imagine que Iterable force l'ajout d'une méthode iterator et que les tableaux n'implémentent pas les méthodes. char[] ne remplace même pas toString. Quoi qu'il en soit, les tableaux de références ne devraient pas être considérés comme idéaux - utilisez Lists. Comme le commente dfa, Arrays.asList fera la conversion pour vous, explicitement.

(Ceci dit, vous pouvez appeler clone sur les tableaux.)

72

Le tableau est un objet, mais ses éléments peuvent ne pas l'être. Le tableau peut contenir un type primitif tel que int, auquel Iterable ne peut pas faire face. Au moins c'est ce que je pense.

57
Gareth Adamson

Les tableaux doivent prendre en charge Iterable, mais ils ne le font tout simplement pas, pour la même raison que les tableaux .NET ne prennent pas en charge une interface qui permet un accès aléatoire en lecture seule par position (aucune interface de ce type n'est définie en standard). Fondamentalement, les frameworks comportent souvent de petites lacunes gênantes, qu’il ne vaut pas la peine de corriger. Peu importe si nous pouvons les réparer nous-mêmes de manière optimale, mais souvent nous ne le pouvons pas.

PDATE: Pour être précis, j'ai mentionné les tableaux .NET ne prenant pas en charge une interface prenant en charge l'accès aléatoire par position (voir aussi mon commentaire). Mais dans .NET 4.5, cette interface exacte a été définie et est prise en charge par les tableaux et le List<T> classe:

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

Tout n'est pas encore parfait car l'interface de liste mutable IList<T> n'hérite pas IReadOnlyList<T>:

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

Peut-être y at-il une compatibilité ascendante possible avec un tel changement.

S'il y a des progrès sur des choses similaires dans les nouvelles versions de Java, je serais intéressé de le savoir dans les commentaires! :)

16
Daniel Earwicker

Malheureusement, les tableaux ne sont pas 'class- assez'. Ils n'implémentent pas l'interface Iterable.

Alors que les tableaux sont maintenant des objets qui implémentent Clonable et Serializable, je crois n tableau n'est pas un objet au sens habituel, et n'implémente pas l'interface.

La raison pour laquelle vous pouvez les utiliser dans chaque boucle est parce que Sun a ajouté du sucre syntaxique pour les tableaux (c'est un cas spécial).

Puisque les tableaux ont commencé comme des "presque objets" avec Java 1, il serait trop radical de les modifier pour les rendre réels objets en Java.

14
jjnguy