Java Generics Wildcard erweitert die letzte Klasse

8

Warum gibt Java beim Kompilieren meiner TestGenerics class keine Warnung aus, wenn man bedenkt, dass String class final ist und nicht erweitert werden kann?

%Vor%     
L4zy 31.07.2013, 12:25
quelle

3 Antworten

7

Nehmen wir an, ich hatte eine Methode wie folgt:

%Vor%

Zugegeben, nicht die beste Signatur der Welt, aber immer noch vollkommen legal. Was würde passieren, wenn ich ein List<String> an diese Methode übergeben würde? Gemäß der Signatur wird ein List<? extends String> zurückgegeben. Wenn Java diesen Typ nicht zulässt, wäre es unmöglich, diese Methode für List<String> zu verwenden (oder zumindest wäre es unmöglich, den Rückgabewert zu verwenden).

Zweitens ist die extends -Syntax in diesem Fall immer noch nützlich, da List<String> und List<? extends String> unterschiedliche Einschränkungen haben - speziell können Sie nichts als null literal zu List<? extends String> hinzufügen. Ich werde manchmal ? extends verwenden, um zu signalisieren, dass eine Sammlung schreibgeschützt ist (da nur T s übergeben werden können, sind null ) und ? super , um schreibgeschützt zu bedeuten (da du nur erhalten kannst aus T s als Object ). Dies ist nicht völlig narrensicher (Sie können immer noch remove-Methoden aufrufen, in null s übergeben, downcast, etc.), aber dient als eine sanfte Erinnerung an, wie die Sammlung wahrscheinlich verwendet werden soll.

    
yshavit 31.07.2013, 12:44
quelle
6

Der Compiler nimmt diese Tatsache nicht wirklich zur Kenntnis, weil das nicht wichtig ist. String s sind weiterhin in der Liste erlaubt, und im Endprodukt wird die Möglichkeit, dass% ce_de% erweitert wird, nicht gefunden. Nach Löschung kommt es folgendermaßen heraus:

%Vor%

Wie Sie sehen, gibt es jetzt keine Vorschläge für eine Klasse, die String erweitert. Wenn Sie eine Klasse erstellen, die String erweitert, ist das selbst ein Kompilierungsfehler. Es gibt keine Notwendigkeit für Javac, sich darüber Sorgen zu machen.

    
tbodt 31.07.2013 12:29
quelle
0

Das Typsystem berücksichtigt List<String> und List<? extends String> nicht, obwohl String zum Zeitpunkt des Kompilierens keine anderen Subtypen als sich selbst hat. Daher muss jedes Objekt, das ein List<? extends String> ist, auch ein% sein. co_de%.

Eine Erklärung ist, dass List<String> nicht endgültig ist - es ist in Ordnung, final aus einer Klasse zu entfernen, und nichts sollte brechen: Ссылка

Es ist nicht selbstverständlich, dass das Typsystem final berücksichtigt; Zum Beispiel können wir final nicht auf String umwandeln, weil der Compiler feststellt, dass wenn ein Objekt Runnable ist, es keine unbekannte Unterklasse sein kann, die String implementiert.

Wenn wir möchten, dass Generika auch solche Schlüsse ziehen und daraus schließen, dass Runnable und List<String> gleichwertig sind, werden die Schreibregeln noch komplizierter.

    
ZhongYu 01.08.2013 01:51
quelle

Tags und Links