Ich frage mich, ob jemand (2) verwendet?
Ja, aber selten aus gutem Grund (IMO).
Und Menschen werden verbrannt, weil sie die ArrayList
wenn sie hätten verwenden sollen List
:
-
Utility-Methoden wie Collections.singletonList(...)
ou Arrays.asList(...)
geben keine ArrayList
.
-
Methoden im List
API garantiert nicht, dass sie eine Liste desselben Typs zurückgibt.
Zum Beispiel, wenn jemand verbrannt wird, in https://stackoverflow.com/a/1481123/139985 das Poster hatte Probleme mit dem "Slicing", weil ArrayList.sublist(...)
gibt keine ArrayList
... und er hatte seinen Code so entworfen, dass er ArrayList
als Typ für alle seine Listenvariablen. Am Ende "löste" er das Problem, indem er die Teilliste in eine neue ArrayList
.
Das Argument, man müsse wissen, wie die List
verhält, wird weitgehend durch die Verwendung der RandomAccess
Marker-Schnittstelle. Ja, sie ist ein bisschen klobig, aber die Alternative ist schlimmer.
Und wie oft erfordert die Situation tatsächlich die Verwendung von (1) anstelle von (2) (d. h. wo (2) nicht ausreicht, abgesehen von der "Kodierung nach Schnittstellen" und bewährten Verfahren usw.)
Der Teil "wie oft" der Frage ist objektiv nicht beantwortbar.
(und kann ich bitte ein Beispiel bekommen)
Gelegentlich kann es vorkommen, dass die Anwendung verlangt, dass Sie Methoden in der ArrayList
API, die no im List
API. Zum Beispiel, ensureCapacity(int)
, trimToSize()
ou removeRange(int, int)
. (Der letzte Punkt tritt nur auf, wenn Sie einen Subtyp von ArrayList erstellt haben, der die Methode als public
.)
Das ist der einzige vernünftige Grund für die Codierung in der Klasse und nicht in der Schnittstelle, IMO.
(Es ist theoretisch möglich, dass Sie eine geringfügige Verbesserung der Leistung erhalten ... unter bestimmten Umständen ... auf einigen Plattformen ... aber es lohnt sich nicht, dies zu tun, es sei denn, Sie brauchen wirklich die letzten 0,05%. Dies ist kein triftiger Grund, IMO.)
Man kann keinen effizienten Code schreiben, wenn man nicht weiß, ob der Zufallszugriff effizient ist oder nicht.
Das ist ein berechtigtes Argument. Allerdings bietet Java bessere Möglichkeiten, damit umzugehen; z.B.
public <T extends List & RandomAccess> void test(T list) {
// do stuff
}
Wenn Sie das mit einer Liste aufrufen, die nicht die RandomAccess
erhalten Sie einen Kompilierungsfehler.
Sie könnten auch dynamisch testen ... mit instanceof
... wenn statische Typisierung zu umständlich ist. Und Sie könnten Ihren Code sogar so schreiben, dass er (dynamisch) unterschiedliche Algorithmen verwendet, je nachdem, ob eine Liste den wahlfreien Zugriff unterstützt oder nicht.
Beachten Sie, dass ArrayList
ist nicht die einzige Listenklasse, die Folgendes implementiert RandomAccess
. Andere umfassen CopyOnWriteList
, Stack
y Vector
.
Ich habe Leute gesehen, die das gleiche Argument über Serializable
(weil List
implementiert es nicht) ... aber der obige Ansatz löst auch dieses Problem. (In dem Maße, in dem es überhaupt lösbar über Laufzeittypen. Eine ArrayList
wird die Serialisierung fehlschlagen, wenn ein Element nicht serialisierbar ist).
Schließlich werde ich nicht sagen, "weil es guter Stil ist". Dieser "Grund" ist sowohl ein Zirkelschluss (" Warum ist es 'guter Stil'?") und ein Appell an eine nicht genannte (und wahrscheinlich nicht existierende!) höhere Autorität (" Wer sagt, es sei 'guter Stil'?").
(Ich halte es für einen guten Stil, an der Schnittstelle zu programmieren, aber ich werde das nicht als Grund anführen. Es ist besser für Sie, das zu verstehen real und kommen Sie zu den (IMO) richtigen Schlussfolgerungen für sich selbst. Die richtige Schlussfolgerung puede nicht immer dasselbe sein ... je nach Kontext).