avec Java5, nous pouvons écrire:
Foo[] foos = ...
for (Foo foo : foos)
ou simplement en utilisant un Iterable dans la boucle for. Ceci 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 l'appelant avec un tableau car ce n'est pas un Iterable:
Foo[] foos = { .. };
bar(foos); // compile time error
Je me demande les raisons de cette décision de conception.
java.lang.reflect.Array
, mais ses performances sont faibles. Cependant, vous pouvez écrire vos propres itérateurs (ou implémentations List!) Pour encapsuler des tableaux de types primitifs si vous le souhaitez.Réponses:
Les tableaux peuvent implémenter des interfaces (
Cloneable
etjava.io.Serializable
). Alors pourquoi pasIterable
? Je suppose que lesIterable
forces ajoutent uneiterator
méthode et que les tableaux n'implémentent pas de méthodes.char[]
ne l'emporte même pastoString
. Quoi qu'il en soit, les tableaux de références devraient être considérés comme moins qu'idéaux - utilisez leList
s. Comme le commente dfa,Arrays.asList
fera la conversion pour vous, explicitement.(Cela dit, vous pouvez faire appel
clone
à des tableaux.)la source
Iterator<T>
nécessite égalementremove(T)
, bien qu'il soit permis de lancer unUnsupportedOperationException
.java.lang.Object
.Le tableau est un objet, mais ses éléments peuvent ne pas l'être. Le tableau peut contenir un type primitif comme int, auquel Iterable ne peut pas faire face. Du moins c'est ce que je pense.
la source
Iterable
interface, les tableaux primitifs doivent être spécialisés pour utiliser les classes wrapper. Cependant, rien de tout cela n'est vraiment grave, car les paramètres de type sont tous faux de toute façon.List<int>
au lieu deList<Integer>
, etc.). Un hack pourrait être fait avec des wrappers mais avec une perte de performances - et plus important encore - si ce hack était fait, cela empêcherait de l'implémenter correctement en Java à l'avenir (par exemple, ilint[].iterator()
serait à jamais verrouillé pour revenirIterator<Integer>
plutôt queIterator<int>
). Peut-être que les prochains types de valeur + spécialisation générique pour Java (projet valhalla) rendront les tableaux implémentésIterable
.Les tableaux devraient prendre en charge
Iterable
, 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 (il n'y a pas d'interface définie comme standard). Fondamentalement, les frameworks ont souvent de petites lacunes ennuyeuses, que personne ne vaut le temps de corriger. Cela n'aurait pas d'importance si nous pouvions les réparer nous-mêmes de manière optimale, mais souvent nous ne pouvons pas.MISE À JOUR: Pour être impartial, j'ai mentionné les tableaux .NET ne prenant pas en charge une interface qui prend 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 la
List<T>
classe:Tout n'est pas encore tout à fait parfait car l'interface de liste mutable
IList<T>
n'hérite pasIReadOnlyList<T>
:Il y a peut-être un possible problème de compatibilité descendante 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 savoir dans les commentaires! :)
la source
IList<T>
expose les opérations de modification. Ce serait génial siIList<T>
avait hérité quelque chose comme uneIReadonlyList<T>
interface, qui aurait juste euCount
etT this[int]
et héritéIEnumerable<T>
(qui soutient déjà l' énumération en lecture seule). Une autre grande chose serait une interface pour obtenir un énumérateur d'ordre inverse, que laReverse
méthode d'extension pourrait interroger (tout comme laCount
méthode d'extension interroge pourICollection
s'optimiser.)IList
etICollection
depuis .NET 1.1,IList<T>
etICollection<T>
depuis .NET 2.0. C'est encore un autre cas où Java est loin derrière la concurrence.IList
est qu'il ne fournit pas plus d'attributs interrogeables. Je dirais qu'un ensemble approprié devrait inclure IsUpdateable, IsResizable, IsReadOnly, IsFixedSize et ExistingElementsAreImmutable pour les débutants. La question de savoir si le code d'une référence peut, sans transtypage, modifier une liste est distincte de la question de savoir si un code qui contient une référence à une liste qu'il n'est pas censé modifier peut en toute sécurité partager cette référence directement avec du code extérieur, ou si il peut supposer que certains aspects de la liste ne changeront jamais.Malheureusement, les tableaux ne sont pas «
class
assez». Ils n'implémentent pas l'Iterable
interface.Alors que les tableaux sont maintenant des objets qui implémentent Clonable et Serializable, je pense qu'un tableau n'est pas un objet au sens normal du terme et n'implémente pas l'interface.
La raison pour laquelle vous pouvez les utiliser dans les boucles for-each est que Sun a ajouté du sucre syntatique pour les tableaux (c'est un cas particulier).
Puisque les tableaux ont commencé comme des «presque objets» avec Java 1, il serait beaucoup trop radical de changer pour en faire de vrais objets en Java.
la source
Cloneable
etSerializable
s'interfacent.Le compilateur traduit en fait le
for each
sur un tableau en une simplefor
boucle avec une variable de compteur.Compiler les éléments suivants
puis décompiler le fichier .class donne
la source