Mit Java5 können wir schreiben:
Foo[] foos = ...
for (Foo foo : foos)
oder einfach ein Iterable in der for-Schleife verwenden. Das ist sehr praktisch.
Sie können jedoch keine generische Methode für iterable wie folgt schreiben:
public void bar(Iterable<Foo> foos) { .. }
und es mit einem Array aufrufen, da es kein Iterable ist:
Foo[] foos = { .. };
bar(foos); // compile time error
Ich frage mich über die Gründe für diese Designentscheidung.
java.lang.reflect.Array
jedoch die Leistung schwach ist. Sie können jedoch Ihre eigenen Iteratoren (oder Listenimplementierungen!) Schreiben, um Arrays primitiver Typen zu verpacken, wenn Sie möchten.Antworten:
Arrays können Schnittstellen (
Cloneable
undjava.io.Serializable
) implementieren . Warum also nichtIterable
? Ich denke,Iterable
erzwingt das Hinzufügen eineriterator
Methode, und Arrays implementieren keine Methoden.char[]
überschreibt nicht einmaltoString
. Auf jeden Fall sollten Referenzarrays als weniger ideal angesehen werden - verwenden SieList
s. Wie dfa kommentiert,Arrays.asList
wird die Konvertierung explizit für Sie durchgeführt.(Allerdings können Sie
clone
Arrays aufrufen .)quelle
Iterator<T>
erfordert auchremove(T)
, obwohl es erlaubt ist ein zu werfenUnsupportedOperationException
.java.lang.Object
.Das Array ist ein Objekt, seine Elemente jedoch möglicherweise nicht. Das Array enthält möglicherweise einen primitiven Typ wie int, mit dem Iterable nicht umgehen kann. Zumindest denke ich das.
quelle
Iterable
Schnittstelle primitive Arrays auf die Verwendung der Wrapper-Klassen spezialisiert sein müssen. Nichts davon ist wirklich eine große Sache, da die Typparameter sowieso alle falsch sind.List<int>
anstelle vonList<Integer>
usw.). Ein Hack könnte mit Wrappern durchgeführt werden, aber mit einem Leistungsverlust - und was noch wichtiger ist - würde dieser Hack in Zukunft verhindern, dass er ordnungsgemäß in Java implementiert wird (zum Beispielint[].iterator()
wäre er für immer gesperrt, um zurückzukehren,Iterator<Integer>
anstattIterator<int>
). Vielleicht werden Arrays durch die bevorstehenden Werttypen + generische Spezialisierung für Java (Projekt valhalla) implementiertIterable
.Arrays sollten dies unterstützen
Iterable
, sie tun dies jedoch nicht, aus dem gleichen Grund, aus dem .NET-Arrays keine Schnittstelle unterstützen, die einen schreibgeschützten Direktzugriff nach Position ermöglicht (es gibt keine solche als Standard definierte Schnittstelle). Grundsätzlich weisen Frameworks oft störende kleine Lücken auf, deren Behebung niemandes Zeit wert ist. Es wäre egal, ob wir sie selbst optimal reparieren könnten, aber oft können wir es nicht.UPDATE: Um ausgeglichen zu sein, habe ich .NET-Arrays erwähnt, die keine Schnittstelle unterstützen, die den wahlfreien Zugriff nach Position unterstützt (siehe auch meinen Kommentar). In .NET 4.5 wurde diese genaue Schnittstelle definiert und wird von Arrays und der
List<T>
Klasse unterstützt:Es ist immer noch nicht alles perfekt, da die veränderbare Listenschnittstelle
IList<T>
nicht erbtIReadOnlyList<T>
:Vielleicht gibt es eine mögliche Abwärtskompatibilität mit einer solchen Änderung.
Wenn es in neueren Versionen von Java Fortschritte bei ähnlichen Dingen gibt, würde ich mich über die Kommentare freuen! :) :)
quelle
IList<T>
macht Operationen zum Ändern verfügbar. Es wäre großartig, wenn Sie soIList<T>
etwas wie eineIReadonlyList<T>
Schnittstelle geerbt hätten, die geradeCount
undT this[int]
und geerbt hätteIEnumerable<T>
(die bereits schreibgeschützte Aufzählung unterstützt). Eine weitere großartige Sache wäre eine Schnittstelle zum Abrufen eines Enumerators in umgekehrter Reihenfolge, nach der dieReverse
Erweiterungsmethode abfragen könnte (genau wie dieCount
ErweiterungsmethodeICollection
IList
&ICollection
seit .NET 1.1IList<T>
undICollection<T>
seit .NET 2.0. Dies ist ein weiterer Fall, in dem Java weit hinter der Konkurrenz zurückliegt.IList
ist, dass es keine abfragbareren Attribute bietet. Ich würde sagen, ein geeigneter Satz sollte für den Anfang IsUpdateable, IsResizable, IsReadOnly, IsFixedSize und ExistingElementsAreImmutable enthalten. Die Frage, ob Code eine Referenz ohne Typumwandlung eine Liste ändern kann, unterscheidet sich von der Frage, ob Code, der eine Referenz auf eine Liste enthält, die nicht geändert werden soll, diese Referenz sicher direkt mit externem Code teilen kann oder ob Es kann davon ausgegangen werden, dass sich ein Aspekt der Liste niemals ändern wird.Leider sind Arrays nicht
class
genug. Sie implementieren dieIterable
Schnittstelle nicht.Während Arrays jetzt Objekte sind, die Clonable und Serializable implementieren, glaube ich, dass ein Array kein Objekt im normalen Sinne ist und die Schnittstelle nicht implementiert.
Der Grund, warum Sie sie in for-each-Schleifen verwenden können, ist, dass Sun etwas synthetischen Zucker für Arrays hinzugefügt hat (dies ist ein Sonderfall).
Da Arrays mit Java 1 als "fast Objekte" begannen, wäre eine Änderung viel zu drastisch, um sie zu echten Objekten in Java zu machen .
quelle
Cloneable
undSerializable
Schnittstellen.Der Compiler übersetzt das
for each
auf einem Array tatsächlich in ein einfachesfor
Schleife mit einer Zählervariablen.Folgendes kompilieren
und dann Dekompilieren der .class-Datei ergibt
quelle