Angenommen, ich habe eine Java-Klasse parametrisiert, die ein privates T_member enthält. Ich möchte einen Standard Konstruktor schreiben (keine Argumente), der irgendwie mein T_member zu irgendeinem bekannten, Typ T spezifischen Wert initialisiert (wie -1 für Integer, Float.MAX_VALUE für Float ...). Ist das möglich? Ich habe versucht, neue T(), aber der Compiler mag das nicht. Oder mache ich nichts, und der Standardkonstruktor wird garantiert für mich aufgerufen?Java-generische Elementinitialisierung
Antwort
Jedes Feld in Java ohne Initialisierungsausdruck wird automatisch mit einem bekannten Standardwert initialisiert. Und ja, in diesem Fall ist es ein bekannter Wert vom Typ T - null
.
Es ist nicht direkt möglich, da es keine Garantie gibt T
sogar hat einen Standardkonstruktor. Sie könnten es jedoch mit Reflektion mit newInstance
tun. Stellen Sie sicher, dass alle möglichen Ausnahmen gefunden werden.
public class MyClass<T> {
private T _member;
public MyClass(Class<T> cls) {
try {
_member = cls.newInstance();
} catch (InstantiationException e) {
// There is no valid no-args constructor.
}
}
}
-1 Mit 'T' können Sie nichts machen. Diese Antwort wird nicht funktionieren. Siehe meine Antwort für warum – Bohemian
OMG! Du hast deine Antwort total geändert und meine Kopie über den Inhalt kopiert. Hast du keine Ehre? – Bohemian
Ich habe Ihre Antwort nicht kopiert und eingefügt. Ich fügte ein Beispiel für meinen zweiten und dritten Satz hinzu. Ich habe deine Antwort aufgefrischt; hier ist kein Schaden beabsichtigt, mein Freund. –
Wegen type erasure, zur Laufzeit "gibt es keine T".
Der Weg darum herum ist eine Instanz von Class<T>
in den Konstruktor übergeben, wie folgt aus:
public class MyClass<T> {
T _member;
public MyClass(Class<T> clazz) {
_member = clazz.newInstance(); // catch or throw exceptions etc
}
}
BTW, ist dies eine sehr häufige Codemuster das Thema „etwas zu tun mit T“
zu lösenDieser Claz hat Razz-Matazz. : D Das ist ein Thema, aber ich konnte nicht widerstehen. – Wug
Sie meinen * Typ * löschen, ich vertraue? (Wäre irgendwie schlecht wenn die * runtime * sich selbst gelöscht ;-) – meriton
Die als Argument übergebene Klasseninstanz wird als [type token] bezeichnet (http://docs.oracle.com/javase/tutorial/extra/generics/ literals.html) – hertzsprung
In der Tat ist ein Weg, dies zu tun, hier ist ein Link zu answer auf verwandten SO Frage.
Also in der Tat Ihre Hauptfrage, wenn es eine Möglichkeit gibt, Klasse des generischen Mitglieds zur Laufzeit zu erhalten? Ja, da ist - mit Reflektion.
Als ich diese Antwort vor einem Jahr kam, habe ich es getestet und die Reflektion ein wenig genauer untersucht. In der Tat gab es einige Fälle, in denen es nicht wie es war (sei es bei Fällen mit Erbschaft), aber im Allgemeinen ist es falsch zu behaupten, dies sei unmöglich.
Ich jedoch stark nicht vorschlagen, tun es so.
BEARBEITEN. Überraschend fand ich meinen eigenen Kommentar unter dieser Antwort :) Und im nächsten Kommentar gibt es einen Link vom Autor zum Originalartikel über die Reflexion von Generika.
- 1. Zyklische Abhängigkeit der Elementinitialisierung
- 2. Nicht verzögerte statische Elementinitialisierung für Vorlagen in gcc?
- 3. C++ auto mit Elementinitialisierung Syntax und gelöscht Copykonstruktor
- 4. Lebensdauer eines temporären Objekt gebunden an ein Referenzelement in Elementinitialisierung Liste (C++ 14)
- 5. Clang ++ Xcode 4.4 Nicht statische Member Initialisierung und Move Konstruktor
- 6. Warum in C# ist dies nicht in Member-Initialisierer erlaubt, aber in VB.Net ist mir erlaubt
- 7. C++ Data Member Initialisierer ist nicht erlaubt
- 8. Konflikt zwischen perfektem Weiterleitungskonstruktor und Kopierkonstruktor in der Klassenhierarchie
Ha sagte gut +1 –