Wie übergibt man eine parametrisierte Klasse als argument
Mein Ziel ist die Entwicklung einer Klasse ausgegeben werden können, ein Objekt der angegebenen Klasse.
public class GetMe<T> {
public T get() {
Object obj = generateObject();
return (T) obj;
}
}
Nun, ich weiß, das ist nicht möglich wegen zu löschen. So, dann können wir auch in einer Klasse-Instanz und verwenden Sie, dass zu werfen.
public class GetMe<T> {
public GetMe<T>(Class<T> clazz) {
this.clazz = clazz;
}
public T get() {
Object obj = generateObject();
return clazz.cast(obj);
}
}
Dieser funktioniert Super! Solange die Klasse nicht parametriert werden. Wenn es ist, dann habe ich ein problem.
Darf ich nicht verwenden List<String>.class
. Wenn ich den pass in einer ParameterizedType (die in sich selbst ist schwer zu erzeugen), gibt es keine cast
Methode zu verwenden.
Gibt es einen Weg aus diesem Sumpf?
- Es ist ein Weg, zu behalten generics zur Laufzeit, aber was ist
generateObject
und warum kann es nicht geben ein Objekt vom TypT
? - Blick auf diese Beispiele, die helfen könnten: serdom.eu/ser/2007/03/25/...
- Lassen Sie uns sagen
generateObject()
ist ein third-party-deserializer. Ich weiß, es ist vom Typ T, weil ich serialisiert es früher, aber die Methode dennoch nur Objekt gibt. Es könnte auch das Ergebnis einer Methode.aufrufen, die nur Objekt gibt. - Yochai: Komisch, ich habe versucht zu tun, was genau eines der Beispiele empfohlen (
(Class<T>) paramType.getActualTypeArguments()[0];
). Leider wird dies oft nicht, da gibt es absolut keine Garantie, dass einType
ist einClass
. Zum BeispielList
ist einType
dass Gießmasse zuClass
, aberList<String>
ist ein Typ, der nicht gewirkt zuClass
. - Kaufen Sie können nicht erstellen Sie eine Instanz des List<String> sowieso..., die Sie brauchen, um eine tatsächliche Klasse. (new ArrayList<Zeichenfolge>() ) .... Liste<> ist eine Schnittstelle. Sie können eine Einschränkung zu garantieren, es ist ein Objekt: public class GetMe<T extends Object>
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich denke super type tokens kann dieses problem lösen für Sie.
Das problem mit
List<String>
ist, dass, wegen der Löschung, wäre es zur Laufzeit nicht zu unterscheiden von einem anderenList<?>
. Der einfachste Weg, um dieses ist, um erstellen Sie eine neue Klasse oder Schnittstelle, die den generischen Teil "Feste", wieDiese Weise haben Sie eine Art token (die
StringList.class
Objekt), die Sie übergeben können, um zur Laufzeit und gibt genau das, was Sie wollen, aber ohne die Notwendigkeit für die generics zur Laufzeit.Map<Domain, Map<String, Number>>
, wo die Domain könnte man von ~200 Objekt, von denen einige selbst parametriert werden.Hier ist nur eine kleine Idee. Ich bin mir nicht wirklich sicher, ob es passen in den Zusammenhang, aber trotzdem:
Prost!
Das erste problem ist, wie Sie planen, Sie zu instanziieren
List
Objekt. Wenn Sie uns mehr von dem, was Sie versuchen zu bauen, wir können Ihnen helfen, besser.Können Sie verwenden möchten, Geben Sie anstelle von Klasse. Typ darstellen kann, sind alle generischen Typen, die, obwohl es ist nicht angenehm, mit zu arbeiten.
Weiteres problem ist, wie man erstellen Sie einen generischen Typ, wie
List<String>
. Die "super type-token" sieht gut aus, in der syntax, in Wirklichkeit ist es im GrundeIch würde viel lieber auf diese Weise
Tatsächlich, viele dieser frameworks, der Lust runtime generic Magie arbeiten auf Instanz-Felder nur.
Ich denke, die Verwirrung kommt von der Tatsache, dass Sie versuchen, ein Objekt zu erstellen, aus
List<>
die im Gesicht es eine Schnittstelle, nicht ein Objekt.Also, egal was Sie versuchen würde, Sie nur können nicht erstellen Sie eine Instanz der
List<>
, (Schnittstellen sind keine echten Klassen, und nicht Konstruktoren)Versuchen Sie es mit einer Einschränkung zu vermeiden, dass die Schnittstellen setzen in der Erklärung:
Hierdurch wird sichergestellt, dass T ist eine Klasse und kein interface.