Was bedeutet Klasse <?> In Java?

Antworten:

109

Classist eine parametrierbare Klasse, daher können Sie die Syntax verwenden, Class<T>wobei Tes sich um einen Typ handelt. Durch das Schreiben Class<?>deklarieren Sie ein ClassObjekt, das von einem beliebigen Typ sein kann ( ?ein Platzhalter ist). Der ClassTyp ist ein Typ, der Metainformationen zu einer Klasse enthält.

Es ist immer eine gute Praxis, sich auf einen generischen Typ zu beziehen, indem Sie seinen spezifischen Typ angeben, indem Class<?>Sie diese Praxis respektieren (Sie wissen Class, dass Sie parametrierbar sind), aber Sie beschränken Ihren Parameter nicht darauf, einen bestimmten Typ zu haben.

Referenz zu Generika und Platzhaltern: http://docs.oracle.com/javase/tutorial/java/generics/wildcards.html

Referenz zu ClassObjekt und Reflexion (die Funktion der Java-Sprache, die zur Selbstbeobachtung verwendet wird): https://www.oracle.com/technetwork/articles/java/javareflection-1536171.html

Manub
quelle
7
Was ist der Vorteil, wenn Sie dies einfach nur Classohne Typ verwenden? Sie scheinen dasselbe zu repräsentieren.
Asche999
1
Ich dachte, der springende Punkt eines Generikums ist, dass Sie den Klassentyp nicht im Voraus kennen. Andernfalls würden Sie nur eine Funktion definieren, um einen bestimmten Klassentyp für den Parameter zu verwenden. Dieses Fragezeichen macht immer noch keinen Sinn.
Brain2000
5
Es gibt keinen anderen Vorteil, außer dass Sie dem Compiler sagen: "Ich weiß, dass dies eine generische Klasse ist, aber ich kenne den tatsächlichen Typ nicht oder kümmere mich nicht darum. Anstatt einen konkreten Typ anzugeben, gebe ich den ?Platzhalter." . Wenn Sie den Platzhalter nicht angeben, geht der Compiler davon aus, dass Sie entweder den Typ vergessen haben oder nicht wussten, dass die Klasse generisch ist, und warnt Sie davor.
Kayaman
1
Was ist das Kotlin-Äquivalent vonClass<?>
JGuo
Classkann einfach nicht an ein Argument übergeben werden, welcher Typ ist Class<?>, Class<?>ist also für alle Situationen bequemer.
Petertc
72

Das <?>ist ein Biest. Es führt oft zu Verwirrung und Fehlern, denn wenn Sie es zuerst sehen, dann beginnen Sie zu glauben, dass <?>es ein Platzhalter für jeden Java-Typ ist . Was nicht wahr ist. <?>ist der unbekannte Typ , ein kleiner und böser Unterschied.

Es ist kein Problem, wenn Sie es mit verwenden Class. Beide Zeilen funktionieren und kompilieren:

Class anyType = String.class;
Class <?> theUnknownType = String.class;

Aber - wenn wir anfangen, es mit Sammlungen zu verwenden, sehen wir seltsame Fehler bei der Kompilierung:

List<?> list = new ArrayList<Object>();  // ArrayList<?> is not allowed
list.add("a String");                    // doesn't compile ...

Unsere List<?>ist keine Sammlung, die für jede Art von Objekt geeignet ist. Es kann nur einen Typ speichern: den mystischen "unbekannten Typ". Welches ist sicher kein richtiger Typ.

Andreas Dolk
quelle
8

Dies bedeutet, dass Ihre Klassenreferenz eine Referenz auf ein beliebiges Klassenobjekt enthalten kann.

Es ist im Grunde dasselbe wie "Klasse", aber Sie zeigen anderen Personen, die Ihren Code lesen, dass Sie Generika nicht vergessen haben. Sie möchten nur eine Referenz, die jedes Klassenobjekt enthalten kann.

Bruce Eckel, Denken in Java:

In Java SE5 wird die Klasse <?> Der einfachen Klasse vorgezogen, obwohl sie gleichwertig ist und die einfache Klasse, wie Sie gesehen haben, keine Compiler-Warnung erzeugt. Der Vorteil von Klasse <?> Besteht darin, dass Sie nicht nur aus Versehen oder aus Unwissenheit eine unspezifische Klassenreferenz verwenden. Sie haben die unspezifische Version gewählt.

Filip
quelle
1
Das Zitat besagt, dass "Klasse <?> Der einfachen Klasse vorgezogen wird" und "Der Vorteil der Klasse <?>". Es scheint, dass blockquote nicht mit den eckigen Klammern übereinstimmt.
Filip
1
Es muss entkommen werden. Es wurde jetzt
behoben
5

Es ist ein Generika- Literal. Dies bedeutet, dass Sie den Klassentyp, den diese ClassInstanz darstellt, nicht kennen , aber weiterhin die generische Version verwenden.

  • Wenn Sie die Klasse kennen würden, würden Sie verwenden Class<Foo>. Auf diese Weise können Sie beispielsweise ohne Casting eine neue Instanz erstellen:Foo foo = clazz.newInstance();
  • Wenn Sie überhaupt keine Generika verwenden, erhalten Sie zumindest eine Warnung (und die Nichtverwendung von Generika wird im Allgemeinen nicht empfohlen, da dies zu schwer zu erkennenden Nebenwirkungen führen kann).
Bozho
quelle
5

In Generika wird ein unbekannter Typ durch das Platzhalterzeichen "?" Dargestellt. Lesen Sie hier für ein offizielles Beispiel.

Jasonw
quelle
3

Das bedeutet eine Klasse mit einer Art von irgendetwas (unbekannt).

Sie sollten das Java Generics Tutorial lesen, um es besser zu verstehen

fmucar
quelle