Ich stoße auf Java-Code wie folgt:
public interface Foo<E> {}
public interface Bar<T> {}
public interface Zar<?> {}
Was ist der Unterschied zwischen allen drei oben genannten und wie nennen sie diese Art von Klassen- oder Schnittstellendeklarationen in Java?
Antworten:
Nun, es gibt keinen Unterschied zwischen den ersten beiden - sie verwenden nur unterschiedliche Namen für den Typparameter (
E
oderT
).Die dritte ist keine gültige Deklaration -
?
wird als Platzhalter verwendet, der bei der Bereitstellung eines Typarguments verwendet wird , z. B.List<?> foo = ...
bedeutet, dassfoo
auf eine Liste eines Typs verwiesen wird, aber wir wissen nicht, was.All dies sind Generika , was ein ziemlich großes Thema ist. Möglicherweise möchten Sie dies anhand der folgenden Ressourcen erfahren, obwohl natürlich weitere verfügbar sind:
quelle
T
undE
- sie sind nur Bezeichner. Sie könntenKeyValuePair<K, V>
zum Beispiel schreiben .?
hat jedoch eine besondere Bedeutung.Es ist mehr Konvention als alles andere.
T
soll ein Typ seinE
soll ein Element sein (List<E>
: eine Liste von Elementen)K
ist der Schlüssel (in aMap<K,V>
)V
ist Wert (als Rückgabewert oder abgebildeter Wert)Sie sind vollständig austauschbar (trotz Konflikten in derselben Erklärung).
quelle
Die vorherigen Antworten erläutern die Typparameter (T, E usw.), erklären jedoch nicht den Platzhalter "?" Oder die Unterschiede zwischen ihnen, daher werde ich darauf eingehen.
Um es klar zu machen: Die Platzhalter- und Typparameter sind nicht identisch. Wenn Typparameter eine Art Variable (z. B. T) definieren, die den Typ für einen Bereich darstellt, ist dies beim Platzhalter nicht der Fall: Der Platzhalter definiert nur eine Reihe zulässiger Typen, die Sie für einen generischen Typ verwenden können. Ohne Begrenzung (
extends
odersuper
) bedeutet der Platzhalter "hier einen beliebigen Typ verwenden".Der Platzhalter steht immer in spitzen Klammern und hat nur im Zusammenhang mit einem generischen Typ eine Bedeutung:
noch nie
oder
Es wird verwirrender, wo sie sich überschneiden. Beispielsweise:
Es gibt viele Überschneidungen bei den Methodendefinitionen. Die folgenden sind funktional identisch:
Also, wenn es Überlappungen gibt, warum das eine oder das andere verwenden? Manchmal ist es ehrlich gesagt nur Stil: Einige Leute sagen, wenn Sie keinen Typparameter benötigen , sollten Sie einen Platzhalter verwenden, um den Code einfacher / lesbarer zu machen. Ein Hauptunterschied, den ich oben erklärt habe: Typparameter definieren eine Typvariable (z. B. T), die Sie an anderer Stelle im Bereich verwenden können. der Platzhalter nicht. Ansonsten gibt es zwei große Unterschiede zwischen Typparametern und dem Platzhalter:
Typparameter können mehrere Begrenzungsklassen haben. Der Platzhalter kann nicht:
Der Platzhalter kann Untergrenzen haben. Typparameter können nicht:
Oben
List<? super Integer>
definiert dasInteger
als Untergrenze des Platzhalters, was bedeutet, dass der Listentyp Integer oder ein Supertyp von Integer sein muss. Generische Typbegrenzungen gehen über das hinaus, was ich im Detail behandeln möchte. Kurz gesagt, Sie können definieren, welche Typen ein generischer Typ sein kann. Dies ermöglicht die polymorphe Behandlung von Generika. ZB mit:Sie können einen Pass
List<Integer>
,List<Float>
,List<Byte>
etc. fürnumbers
. Ohne Typbegrenzung funktioniert dies nicht - so sind Generika.Schließlich ist hier eine Methodendefinition, die den Platzhalter verwendet, um etwas zu tun, von dem ich glaube, dass Sie es nicht anders machen können:
numberSuper
kann eine Liste der Zahlen oder ein beliebiger Supertyp der Zahl sein (z. B.List<Object>
) undelem
muss Zahl oder ein beliebiger Untertyp sein. Bei allen.add()
Einschränkungen kann der Compiler sicher sein, dass dies typsicher ist.quelle
Eine Typvariable <T> kann ein beliebiger nicht primitiver Typ sein, den Sie angeben: ein beliebiger Klassentyp, ein beliebiger Schnittstellentyp, ein beliebiger Array-Typ oder sogar eine andere Typvariable.
Die am häufigsten verwendeten Typparameternamen sind:
In Java 7 ist es erlaubt, wie folgt zu instanziieren:
quelle
Die am häufigsten verwendeten Typparameternamen sind:
Diese Namen werden in der gesamten Java SE-API verwendet
quelle
Der Compiler erstellt für jeden Platzhalter (z. B. Fragezeichen in der Liste) eine Erfassung , wenn er eine Funktion wie die folgende bildet:
Ein generischer Typ wie V wäre jedoch in Ordnung und würde ihn zu einer generischen Methode machen :
quelle