übersicht - java set example




Java-Auflistungs-API: Warum sind nicht änderbare[List | Set | Map] nicht öffentlich sichtbare Klassen? (5)

  • Möglichkeit, einen spezifischeren Rückgabewert anzugeben (z. B. UnmodifiableList ), damit ein API-Benutzer nicht auf die Idee kommt, diese Sammlung zu ändern;

In einer geeigneten API sollte dies bereits im Javadoc der Methode dokumentiert sein, die die nicht änderbare Liste zurückgibt.

  • Möglichkeit, während der Laufzeit zu prüfen, ob eine List eine instanceof UnmodifiableList .

Ein solcher Bedarf zeigt, dass das eigentliche Problem woanders liegt. Es ist ein Fehler im Code-Design. Fragen Sie sich selbst: LinkedList Sie jemals die Notwendigkeit zu prüfen, ob eine List eine Instanz von ArrayList oder LinkedList ? Ob es sich um eine ArrayList , LinkedList oder UnmodifiableList ist eindeutig eine Entscheidung, die während der Code-Schreibzeit getroffen werden muss, nicht während der Code-Laufzeit. Wenn Sie Probleme haben, weil Sie versuchen, eine UnmodifiableList zu modifizieren (für die der API-Entwickler möglicherweise sehr gute Reaktionen hat, die bereits dokumentiert sein sollten), dann ist es eher Ihre eigene Schuld, kein Laufzeitfehler.

Alles in allem macht es keinen Sinn. Die Collections#unmodifiableXXX() , synchronizedXXX() und checkedXXX() repräsentieren in keiner Weise konkrete Implementierungen. Sie sind alles nur decorators die unabhängig von der zugrunde liegenden konkreten Implementierung angewendet werden können.

Collections.unmodifiableList(...) gibt eine neue Instanz einer statischen inneren Klasse UnmodifiableList . Andere nicht änderbare Auflistungsklassen sind auf dieselbe Weise aufgebaut.

Waren diese Klassen öffentlich, hatte man zwei Vorteile:

  • Möglichkeit, einen spezifischeren Rückgabewert anzugeben (z. B. UnmodifiableList ), damit ein API-Benutzer nicht auf die Idee kommt, diese Sammlung zu ändern;
  • Möglichkeit, während der Laufzeit zu prüfen, ob eine List eine instanceof UnmodifiableList .

Also, gab es irgendwelche Vorteile, diese Klassen nicht öffentlich zu machen?

EDIT : Es wurden keine definitiv überzeugenden Argumente vorgebracht, daher wähle ich die am häufigsten gestellte Antwort.


Angenommen, UnmodifiableList war eine öffentliche Klasse. Ich vermute, dass es Programmierer in ein falsches Gefühl der Sicherheit bringen würde. Denken Sie daran, UnmodifiableList ist eine Ansicht einer modifizierbaren List . Dies bedeutet, dass der Inhalt einer UnmodifiableList sich noch ändern kann, wenn Änderungen an der zugrunde liegenden List . Ein naive Programmierer mag diese Nuance nicht verstehen und kann erwarten, dass Instanzen von UnmodifiableList unveränderlich sind.


Ich denke beide Vorteile sind da, aber sind nicht so nützlich. Die Hauptprobleme bleiben die gleichen: UnmodiableList ist immer noch eine Liste und somit sind alle Setter verfügbar und die zugrundeliegenden Sammlungen sind noch modifizierbar. Wenn die Klasse "UnmodiableList" öffentlich gemacht würde, würde dies zu der Illusion beitragen, nicht veränderbar zu sein.

Der bessere Weg wäre, dass der Compiler hilft, aber dafür müssten sich die Sammelklassenhierarchien stark ändern. ZB ist die Collection-API von Scala in dieser Hinsicht weit fortgeschritten.

Ein Nachteil wäre die Einführung von mindestens drei zusätzlichen Klassen / Schnittstellen in die API. Da sie nicht so nützlich sind, denke ich, dass es eine gute Wahl ist, sie aus der API herauszulassen.


Ich denke, die Antwort liegt darin, dass die Methodenform die verwendeten Generika richtig kennt und keine zusätzliche Programmierung benötigt, um diese Information weiterzugeben, während das Klassenformular mehr Unordnung erfordert. Das Methodenformular für unmodifiableMap enthält zwei sich unmodifiableMap und herbewegende generische Argumente, die sowohl den generischen Argumenten des Rückgabetyps als auch des übergebenen Arguments zugeordnet werden.

public static <K,V> Map<K,V> unmodifiableMap(Map<? extends K, ? extends V> m) {
    return new UnmodifiableMap<K,V>(m);
}

Wenn es für Sie wichtig ist, zu überprüfen, ob die Liste mit Collections.unmodiableList erstellt wurde, können Sie eine Instanz erstellen und nach der Klasse fragen. Jetzt können Sie diese Klasse mit der Klasse einer beliebigen Liste vergleichen.

private static Class UNMODIFIABLE_LIST_CLASS = 
    Collections.unmodifiableList( new ArrayList() ).getClass();
...
if( UNMODIFIABLE_LIST_CLASS == listToTest.getClass() ){
    ...
} 




unmodifiable