public class MyGeneric<T, E> {}
public class Extend1<T, E> extends MyGeneric<T, E> {}
public class Extend2 extends MyGeneric<String, Object> {}
Soweit mir bekannt ist, sind beide Unterklassen im obigen Beispiel gültig. Ich habe mich gefragt, woher Java weiß, wann die in der Oberklasse angegebenen Typen definiert werden, wenn die Unterklasse instanziiert wird, und wann es sich um tatsächliche Klassennamen handelt (dh woher weiß es, dass T, E keine Klassennamen sind)?
Eine Nebenbemerkung, ist es zulässig (auch wenn es ungewöhnlich ist), mehr als einen Buchstaben für die generischen Typen zu verwenden? Was ist, wenn (durch einen schwerwiegenden Planungsfehler) die Typen mit einer vorhandenen Klasse in Konflikt geraten, z
public class E{}
public class Foo<E>{}
was passiert dann?
Bearbeiten: Danke, dass du so schnell geantwortet hast. Um meine erste Frage zu beantworten, Joachims Antwort ist am effektivsten.
Um den Randpunkt zu beantworten, ist die Antwort von aioobe klarer
Schauen wir uns diese Definition an:
public class Extend1<T, E> extends MyGeneric<T, E> {}
Hier T und E sind jeweils zweimal und in zwei verschiedenen Rollen präsent
in Extend1<T,E> Sie definieren Argumente eingeben. Das bedeutet, dass der Typ Extend1 hat zwei (unbegrenzte) Typargumente T und E. Dies teilt dem Java-Compiler mit, dass diejenigen, die verwendenExtend1 Typen angeben müssen.
in extends MyGeneric<T,E> Sie verwenden die zuvor definierten Typargumente. Wenn T und E waren hier also nicht als Typargumente bekannt T und E wären einfache Typreferenzen, dh der Compiler würde nach benannten Klassen (oder Interfaces, …) suchen T und E (und höchstwahrscheinlich nicht finden).
Ja, Typargumente folgen denselben syntaktischen Regeln wie jeder andere Bezeichner in Java, sodass Sie mehrere Buchstaben verwenden können ABC oder sogar Namen, die verwirrend sein können (unter Verwendung eines Typarguments namens String ist legal, aber höchst verwirrend).
Ein-Buchstaben-Argumentnamen sind einfach eine sehr verbreitete Benennungsstrategie.
Wenn also Extend1 Generic erweitert, betrachtet der Compiler den ersten “String” als Typ-Argument (anders als java.lang.String) und den zweiten “String” als Typreferenz auf den ersten?
– klein
5. Februar 2015 um 22:08 Uhr
@pegausbupt: Genau, es würde einen Typargumentnamen erstellen String das hat keinen wirklichen Bezug zu java.lang.String außer Leute zu verwirren und diesen Kurznamen zu verstecken.
– Joachim Sauer
15. Februar 2017 um 22:57 Uhr
Im Extend1<T, E>das T und E sind Parameter eingeben. Wann generischer Typaufruf passiert, die T und E in extends MyGeneric<T, E> würde ersetzt durch Argumente eingeben die Typparameter ersetzt T und E in Extend1<T, E>. Tatsächlich können also sowohl generische als auch nicht generische Typen nur nicht generische Typen erweitern/implementieren.
– rosshjb
10. Dezember 2021 um 16:23 Uhr
aiobe
Ich habe mich gefragt, woher Java weiß, wann die in der Oberklasse angegebenen Typen definiert werden, wenn die Unterklasse instanziiert wird, und wann es sich um tatsächliche Klassennamen handelt (dh woher weiß es, dass T, E keine Klassennamen sind)?
Java ist das egal. Wenn Sie tun…
class MyGeneric<String> extends ArrayList<String> {
String value;
}
Ist es zulässig (auch wenn es ungewöhnlich ist), mehr als einen Buchstaben für die generischen Typen zu verwenden? Was ist, wenn (durch einen schwerwiegenden Planungsfehler) die Typen mit einer vorhandenen Klasse in Konflikt geraten, z
Ja, Sie können jeden gültigen Java-Bezeichner für Typparameter verwenden.
Namen können in Konflikt stehen, aber Java behandelt dies nicht als Fehler. Identifikatoren zwischen <…> werden immer als Typparameter behandelt, unabhängig davon, ob der Bezeichner einem Klassennamen entspricht.
Es kann jedoch ziemlich verwirrend werden. Hier ist ein Beispiel:
class MyGeneric<String> extends java.util.ArrayList<String> {
String value;
}
class Test {
public static void main(String... args) throws Exception {
MyGeneric<Integer> obj = new MyGeneric<Integer>();
obj.value = 5;
// ^
// |
// '--- Assign an integer to what seems to be a String!
}
}
Ähnliche Frage:
Unboxing-Probleme
Danke, das hat einiges geklärt (musste es aber ein paar Mal lesen, um es zu verstehen)
– James
31. August 2011 um 10:48 Uhr
Kein Problem, gerne geschehen 🙂 Gute Frage übrigens. Ich habe andere Fragen gesehen, in denen gefragt wurde, warum class MyList<Integer> extends ArrayList<Integer> funktioniert nicht wie erwartet 🙂
– aiobe
31. August 2011 um 10:49 Uhr
Zur Verdeutlichung: Wenn Sie dort einen Typnamen eingeben, z. B. String, dann bedeutet String beim Verweis auf ein MyGeneric-Objekt nicht mehr java.lang.String, sondern jetzt “Einen generischen Typ, den ich String genannt habe”.