Die folgende Java-Methode kann nicht kompiliert werden:
%Vor% Fehler erhalten ist:
Typenkonflikt: Konvertierung von Class<capture#3-of ? extends Number>
in Class<? extends T>
Kann jemand erklären, warum Class<? extends T>
ungültig ist, aber Class<? extends Number>
in Ordnung ist?
Javadoc sagt:
%Vor%Der tatsächliche Ergebnistyp ist
Class<? extends |X|>
mit | X | ist das Löschen des statischen Typs des Ausdrucks, auf dem getClass aufgerufen wird. In diesem Codefragment ist beispielsweise keine Umwandlung erforderlich:
Weil der Typ T
class nicht von T
ausgeht. Stattdessen erstreckt es sich von Number
genau so, wie Sie es in <T extends Number>
deklariert haben. So einfach ist das.
Eine bessere Frage wäre:
Warum kompiliert das folgende nicht?
%Vor%
Die Antwort darauf ist, dass Object#getClass()
Class<?>
mit einem unbegrenzten Platzhalter ?
zurückgibt, da das Objekt selbst nicht direkt über seinen generischen Typ Bescheid weiß, der in einer beliebigen Methode erwartet wurde.
Es ist irgendwie albern. Für die meisten Anwendungsfälle wäre es besser gewesen, wenn x.getClass()
Class<? extends X>
anstatt der gelöschten Class<? extends |X|>
zurückgibt.
Das Löschen ist die Ursache für den Verlust von Informationen, wodurch Ihr scheinbar sicherer Code nicht kompiliert werden kann. t.getClass()
gibt Class<? extends |T|>
und |T| = Number
zurück, so dass Class<? extends Number>
zurückgegeben wird.
Die Löschung (in der Sprachspezifikation vorgeschrieben) dient der Wahrung der theoretischen Korrektheit. Zum Beispiel
%Vor% Obwohl c2 sehr vernünftig erscheint, gibt es in Java wirklich keine solche Klasse für List<String>
. Es gibt nur die Klasse für List
. Also wäre c2 theoretisch falsch.
Diese Formalität hat viele Probleme in der realen Welt verursacht, wo Programmierer sagen können, dass Class<? extends X>
für ihre Zwecke sicher ist, aber mit der gelöschten Version zurechtkommen muss.
Sie können einfach Ihr eigenes getClass
definieren, das den nicht gelöschten Typ
Tags und Links java reflection generics