Eine Instanz generischen Typs in Java erstellen?
Ist es möglich, erstellen Sie eine Instanz der generischen Typen in Java? Ich denke, nach dem, was ich gesehen habe, dass die Antwort no
(aufgrund der type erasure), aber mich würde interessieren, ob jemand sehen kann, was ich bin fehlt:
class SomeContainer<E>
{
E createContents()
{
return what???
}
}
EDIT: Es stellt sich heraus, dass Super Type Tokens verwendet werden könnten, zu beheben mein Problem, aber es erfordert eine Menge der Reflexion-basierten code, wie einige der Antworten, die Sie unten angegeben haben.
Ich lasse diese öffnen, für eine kleine Weile, um zu sehen, wenn jemand kommt, etwas dramatisch anders als Ian Robertson Artima Artikel.
InformationsquelleAutor der Frage David Citron | 2008-09-16
Du musst angemeldet sein, um einen Kommentar abzugeben.
Sind Sie richtig. Sie können nicht
new E()
. Aber Sie können es ändern, umEs ist ein Schmerz. Aber es funktioniert. Das einpacken in der Fabrik-Muster macht es ein wenig erträglicher.
InformationsquelleAutor der Antwort Justin Rudd
Weiß nich ob das hilft, aber wenn Sie eine Unterklasse (einschließlich anonym) ein generischer Typ, der Typ-Informationen verfügbar, über die Reflexion. z.B.,
So, wenn Sie eine Unterklasse von Foo ist, erhalten Sie eine Instanz von Bar z.B.,
Aber es ist eine Menge Arbeit, und funktioniert nur für Unterklassen. Kann praktisch sein, aber.
InformationsquelleAutor der Antwort noah
Werden Sie brauchen eine Art der abstrakten Fabrik der einen oder anderen Art übergeben den schwarzen Peter zu:
InformationsquelleAutor der Antwort Tom Hawtin - tackline
In Java 8 können Sie die
Lieferant
funktionale Schnittstelle zu erreichen, ist das ziemlich einfach:Würden Sie den Bau dieser Klasse wie folgt aus:
Die syntax
String::new
auf dieser Linie ist eine Konstruktor-Referenz.Wenn Ihr Konstruktor übernimmt Argumente, die Sie verwenden können einen lambda-Ausdruck statt:
InformationsquelleAutor der Antwort Daniel Pryden
InformationsquelleAutor der Antwort Lars Bohl
Wenn Sie eine neue Instanz einer Typ-argument innerhalb einer generischen Klasse dann Ihre Konstruktoren Nachfrage seiner Klasse...
Verwendung:
Vorteile:
Nachteile:
Foo<L>
Beweis. Für den Anfang...newInstance()
werfen einen wobbler, wenn das argument Typ Klasse keinen default-Konstruktor. Dies gilt für sämtliche bekannten Lösungen, aber trotzdem.InformationsquelleAutor der Antwort R2D2M2
Können Sie dies jetzt zu tun und es nicht erforderlich ist, eine Reihe von Reflexions-code.
Natürlich, wenn Sie benötigen, rufen Sie den Konstruktor, der eine gewisse Reflexion, aber das ist sehr gut dokumentiert ist, ist dieser trick nicht!
Hier ist die JavaDoc für TypeToken.
InformationsquelleAutor der Antwort feeling unwelcome
Denke über einen mehr funktionalen Ansatz: statt die Entwicklung von einigen E aus dem nichts (und das ist eindeutig ein code smell), übergeben Sie eine Funktion, die weiß, wie man eine zu erstellen, d.h.
InformationsquelleAutor der Antwort Ingo
Vom Java Tutorial - Einschränkungen für Generika:
Kann nicht Erstellen Sie Instanzen der Typ-Parameter
Können Sie erstellen eine Instanz eines type-Parameters. Zum Beispiel, der folgende code führt zu einem compile-Zeit-Fehler:
Als Problemumgehung können Sie erstellen ein Objekt vom Typ parameter durch Reflexion:
Sie aufrufen können Sie die append-Methode wie folgt:
InformationsquelleAutor der Antwort Sergiy Sokolenko
Hier ist eine option, die ich mir ausgedacht habe, vielleicht hilft es:
EDIT: Alternativ können Sie verwenden Sie diesen Konstruktor, (aber es ist eine Instanz von E):
InformationsquelleAutor der Antwort Mike Stone
Wenn Sie wollen nicht die Typ-Klasse name zweimal während der Instanziierung wie in:
Können Sie die factory-Methode:
Wie in:
InformationsquelleAutor der Antwort jb.
Beim arbeiten mit E zur compile-Zeit, die Sie nicht wirklich interessieren, die tatsächlichen generischen Typ "E" (entweder über die Reflexion oder die Arbeit mit der Basis-Klasse generischer Typ) lassen Sie uns also die Unterklasse liefern Instanz von E.
InformationsquelleAutor der Antwort Ira
Können Sie verwenden:
Aber Sie brauchen, um zu liefern die genauen Klassennamen, einschließlich der Pakete, zB.
java.io.FileInputStream
. Ich verwendet diese zum erstellen eines mathematischen Ausdrucks-parser.InformationsquelleAutor der Antwort
Java leider nicht erlauben, was Sie tun möchten. Sehen http://docs.oracle.com/javase/tutorial/java/generics/restrictions.html#createObjects
InformationsquelleAutor der Antwort Neepsnikeep
Dachte ich, ich könnte das tun, aber ziemlich enttäuscht: es funktioniert nicht, aber ich denke, dass es noch lohnt zu teilen.
Vielleicht kann jemand korrigieren:
Produziert:
Zeile 26 ist die mit den
[*]
.Ist die einzige praktikable Lösung ist der von @JustinRudd
InformationsquelleAutor der Antwort Luigi R. Viggiano
Einer imporovement von @Noah ' s Antwort.
Grund für die Änderung
a] Ist sicherer, wenn mehr als 1 generischer Typ wird verwendet, wenn Sie die Reihenfolge ändern.
b] Eine Klasse generische geben Sie die Signatur ändert sich von Zeit zu Zeit, so dass Sie nicht überrascht sein, unerklärliche Ausnahmen, die in der Laufzeit.
Robusten Code
Oder verwenden Sie den liner
Eine Zeile Code
InformationsquelleAutor der Antwort zatziky
Als Sie sagte, Sie kann nicht wirklich tun es, weil der type erasure. Sie können sozusagen tun Sie es mit der spiegelung, aber es erfordert eine Menge von code und Menge der Fehlerbehandlung.
InformationsquelleAutor der Antwort Adam Rosenfield
Wenn du meinst
new E()
dann ist es unmöglich. Und ich möchte hinzufügen, dass es ist nicht immer richtig, wie wollen Sie wissen, ob E ein öffentlich-no-args-Konstruktor?
Aber man kann immer delegieren Schöpfung, um einige der anderen Klasse, die weiß, wie man erstellen Sie eine Instanz - es kann sein
Class<E>
oder Ihre benutzerdefinierte code wie folgtInformationsquelleAutor der Antwort Pavel Feldman
InformationsquelleAutor der Antwort Rachid
Können Sie erreichen dies mit dem folgenden snippet:
InformationsquelleAutor der Antwort bogdan
Gibt es verschiedene Bibliotheken, die aufgelöst
E
für Sie mit Techniken ähnlich zu dem, was die Robertson-Artikel diskutiert. Hier ist eine ImplementierungcreateContents
verwendet TypeTools zu beheben, die raw-Klasse vertreten durch E:Dies setzt Voraus, dass getClass() wird eine Unterklasse von SomeContainer und wird scheitern sonst, da die tatsächliche parametrisierten Wert von E wird gelöscht, zur Laufzeit, wenn es nicht gefangen in einer Unterklasse.
InformationsquelleAutor der Antwort Jonathan
Hier ist eine Implementierung von
createContents
verwendet TypeTools zu beheben, die raw-Klasse vertreten durchE
:Dieser Ansatz funktioniert nur, wenn
SomeContainer
ist untergeordnet, so dass der tatsächliche Wert desE
ist gefangen in einer Art definition:Sonst ist der Wert von E wird zur Laufzeit gelöscht und ist nicht wiederherstellbar.
InformationsquelleAutor der Antwort Jonathan
Können Sie mit einem classloader und der name der Klasse, die schließlich einige Parameter.
InformationsquelleAutor der Antwort Roald