Der Grund ist, dass Set<Set<String>>
nicht Set<HashSet<String>>
entspricht! A Set<Set<String>>
kann beliebig Typ Set<String>
enthalten, während Set<HashSet<String>>
nur HashSet<String>
enthalten darf.
Wenn Set<Set<String>> set = new HashSet<HashSet<String>>()
legal wäre, könnten Sie dies auch ohne Fehler:
Set<HashSet<String>> setOfHashSets = new HashSet<HashSet<String>>();
Set<Set<String>> set = setOfHashSets;
set.add(new TreeSet<String>());
HashSet<String> wrong = set.iterator().next(); // ERROR!
Es ist jedoch legal hier eine beschränkte Platzhalter zu verwenden:
Set<? extends Set<String>> set = setOfHashSets;
Dies liegt daran, jetzt erlaubt , die Art des Objekts, das der Satz enthält, ist ? extends Set<String>
... mit anderen Worten, "einige spezifische aber unbekannte Klasse, die Set<String>
implementiert". Da Sie nicht genau wissen, welche Art von Set<String>
es enthalten darf, dürfen Sie nichts hinzufügen (außer null
) ... Sie könnten sich irren, was später zu einem Fehler führt, wie in meinem erstes Beispiel.
Edit:
Beachten Sie, dass die „top level“ Generika Sie in Ihrer Frage beziehen sich auf parametrisierte Typen genannt werden, Typen bedeutet, dass man nehmen oder mehr Typ Parameter. Der Grund dafür, dass Set<Set<String>> set = new HashSet<Set<String>>()
legal ist, ist, dass HashSet<T>
implementiert und daher ein Subtyp von Set<T>
ist. Beachten Sie jedoch, dass der Typparameter T
übereinstimmen muss! Wenn Sie einen anderen Typ S
haben, der ein Subtyp von T
ist, ist ein HashSet<S>
(oder nur ein Set<S>
even) kein Untertyp von Set<T>
! Ich habe den Grund dafür oben erklärt.
Dies ist genau die Situation hier.
Set<Set<String>> set = new HashSet<Set<String>>();
Wenn wir Set<String>
mit T
hier ersetzen, erhalten wir Set<T> set = new HashSet<T>()
. Es ist leicht zu sehen, dass die tatsächlichen Argumente übereinstimmen und dass der Typ auf der rechten Seite der Zuweisung ein Subtyp des Typs auf der linken Seite ist.
Set<Set<String>> set = new HashSet<HashSet<String>>();
Hier haben wir Set<String>
und HashSet<String>
mit T
und S
bzw. zu ersetzen, wo S
ein Subtyp von T
ist. Mit diesem Ergebnis erhalten wir Set<T> set = new HashSet<S>()
. Wie ich oben beschrieben habe, ist HashSet<S>
kein Untertyp von Set<T>
, daher ist die Zuweisung illegal.
Diese Antwort macht nicht viel Sinn für mich. John Kugelman und ColinD illustrieren das Problem sehr deutlich. – erickson
Dies hat nichts damit zu tun, dass der Typparameter "abgeleitet" wird. – ColinD
@ColinD: Richtig. Fest. – haylem