Abgeleitete Platzhalter-Generika im Rückgabetyp
Java kann auf der Grundlage der Argumente (und sogar des Rückgabetyps im Gegensatz zu beispielsweise C #) häufig auf Generika schließen.
Ein typisches Beispiel: Ich habe eine allgemeine KlassePair<T1, T2>
Das speichert nur ein Paar von Werten und kann auf folgende Weise verwendet werden:
Pair<String, String> pair = Pair.of("Hello", "World");
Die Methodeof
sieht einfach so aus:
public static <T1, T2> Pair<T1, T2> of(T1 first, T2 second) {
return new Pair<T1, T2>(first, second);
}
Sehr schön. Dies funktioniert jedoch nicht mehr für den folgenden Anwendungsfall, für den Platzhalter erforderlich sind:
Pair<Class<?>, String> pair = Pair.of((Class<?>) List.class, "hello");
(Beachten Sie die explizite BesetzungList.class
der richtige Typ.)
Der Code schlägt mit folgendem Fehler fehl (von Eclipse bereitgestellt):
Typenkonflikt: Kann nicht konvertieren vonTestClass.Pair<Class<capture#1-of ?>,String>
zuTestClass.Pair<Class<?>,String>
Das explizite Aufrufen des Konstruktors funktioniert jedoch weiterhin wie erwartet:
Pair<Class<?>, String> pair =
new Pair<Class<?>, String>((Class<?>) List.class, "hello");
Kann jemand dieses Verhalten erklären? Ist es beabsichtigt? Ist eswollte? Mache ich etwas falsch oder bin ich auf einen Fehler im Design / Fehler im Compiler gestoßen?
Wilde Vermutung: Das "Capture # 1-of?" Scheint irgendwie zu implizieren, dass der Compiler den Platzhalter im laufenden Betrieb ausfüllt, was den Typ a ergibtClass<List>
und damit die Konvertierung fehlschlägt (vonPair<Class<?>, String>
zuPair<Class<List>, String>
). Ist das richtig? Gibt es eine Möglichkeit, dies zu umgehen?
Der Vollständigkeit halber ist hier eine vereinfachte Version derPair
Klasse:
public final class Pair<T1, T2> {
public final T1 first;
public final T2 second;
public Pair(T1 first, T2 second) {
this.first = first;
this.second = second;
}
public static <T1, T2> Pair<T1, T2> of(T1 first, T2 second) {
return new Pair<T1, T2>(first, second);
}
}