Generische Klassen erweitern

Lesezeit: 4 Minuten

Benutzer-Avatar
James

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 verwenden Extend1 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


Benutzer-Avatar
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”.

    – Lukastorjussen

    31. August 2011 um 11:03 Uhr


Es gibt kein Problem mit:

public class E{}
public class Foo<E>{}

Denn im Rahmen von Foo<E>, E ist ein Typ.

1109720cookie-checkGenerische Klassen erweitern

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy