Ich lese über Typ-Inferenz für Generika, und dieser Code wurde als ein Beispiel zur Verfügung gestellt, das nicht kompiliert werden kann.Java Generics, Typ Inferenz, Vererbung?
import java.io.*;
class LastError<T> {
private T lastError;
void setError(T t){
lastError = t;
System.out.println("LastError: setError");
}
}
class StrLastError<S extends CharSequence> extends LastError<String>{
public StrLastError(S s) {
}
void setError(S s){
System.out.println("StrLastError: setError");
}
}
class Test {
public static void main(String []args) {
StrLastError<String> err = new StrLastError<String>("Error");
err.setError("Last error");
}
}
Und die Erklärung in dem Buch war:
„(Es sieht aus wie die
setError()
Methode inStrLastError
istsetError()
in derLastError
Klasse überschreibt Es ist jedoch nicht der Fall ist, an die.. Zeitpunkt der Kompilierung, das Wissen vom TypS
ist nicht verfügbar.Der Compiler zeichnet daher die Signaturen dieser beiden Methoden alssetError(String)
in Superklasse undsetError(S_extends_CharSequence)
in Unterklasse-behandelt sie als überladene Methoden (nicht überschrieben). In diesem Fall, wenn der Aufruf zusetError()
gefunden wird, der Compiler findet sowohl den überladenen Methoden Matching, in den vieldeutigen Methodenaufruf Fehlern führte.“
Ich verstehe wirklich nicht, warum Typ S
kann nicht bei der Kompilierung abgeleitet werden. String
ist bestanden, wenn der Konstruktor der Klasse aufgerufen werden StrLastError
, und von der API-Dokumentation, tut String
Schnittstelle implementieren CharSequence
, ist so nicht gemeint, dass S
für <S extends CharSequence>
tatsächlich vom Typ String
?
Ich habe das Java Online-Tutorial zum Thema Generics mehrmals gelesen. Ich habe "Type Inference" und Inheritance überprüft, ich weiß einfach nicht, wie das Ganze funktioniert. Ich brauche wirklich eine Erklärung zu dieser Frage.
Die Punkte Ich bin stecken in sind:
- Wenn der Subtyp nicht
S
entscheiden kann, wie kommt der Super-TypT
entscheiden kann, weil die übergeordnete Klasse gebunden haben keine obere? Oder wird daraus abgeleitet, dassT
String
ist, weil der Subtyp zuerst den Konstruktor des Supertyps aufruft? Ich verstehe, dass, wenn der Konstruktor wie aufgerufen wird:
StrLastError<CharSequence> err = newStrLastError<>((CharSequence)"Error");
wird es keine Zweideutigkeit, da es dann zwingende Ebene Methode ist. (Oder bin ich hier auch falsch?)
Jedoch, wie ich am Anfang gesagt, wenn String
übergeben wird, warum nicht S
abgeleitet wird String
sein?
Warum sagen Sie, dass es keinen Kompilierfehler erzeugt? – user43968
Hallo, ich sagte, es sollte kompilieren Fehler in der ersten Zeile meines Posts erzeugen :) –
Yeah nach der Bearbeitung;) bevor es war "der Code sollte am Ende kompilieren Fehler" – user43968