import com.fasterxml.jackson.core.type.TypeReference; new TypeReference<T>(){}
Bogdan Shulga
Antworten:
567
Die kurze Antwort lautet, dass es in Java keine Möglichkeit gibt, den Laufzeittyp generischer Typparameter herauszufinden. Ich empfehle, das Kapitel über das Löschen von Typen im Java-Lernprogramm zu lesen, um weitere Informationen zu erhalten.
Eine beliebte Lösung hierfür besteht darin, den ClassParameter type vom Typ an den Konstruktor des generischen Typs zu übergeben, z
classFoo<T>{finalClass<T> typeParameterClass;publicFoo(Class<T> typeParameterClass){this.typeParameterClass = typeParameterClass;}publicvoid bar(){// you can access the typeParameterClass here and do whatever you like}}
Diese Antwort bietet zwar eine gültige Lösung, es ist jedoch ungenau zu sagen, dass es zur Laufzeit keine Möglichkeit gibt, den generischen Typ zu finden. Es stellt sich heraus, dass das Löschen von Typen weitaus komplexer ist als das Löschen von Decken. Meine Antwort zeigt Ihnen, wie Sie den generischen Klassentyp erhalten.
Ben Thurley
3
@ BenThurley Ordentlicher Trick, aber soweit ich sehen kann, funktioniert er nur, wenn es einen generischen Supertyp gibt, den er verwenden kann. In meinem Beispiel können Sie den Typ von T in Foo <T> nicht abrufen.
Zsolt Török
@webjockey Nein, das solltest du nicht. Das Zuweisen typeParameterClassohne Standardzuweisung im Konstruktor ist vollkommen in Ordnung. Es ist nicht erforderlich, es ein zweites Mal einzustellen.
Adowrath
Dies ist die erste Lösung, die mir in den Sinn kommt, aber manchmal sind es nicht Sie, die Objekte erstellen / initiieren. Sie können den Konstruktor also nicht verwenden. Zum Beispiel beim Abrufen von JPA-Entitäten aus der Datenbank.
Paramvir Singh Karwal
233
Ich suchte nach einer Möglichkeit, dies selbst zu tun, ohne dem Klassenpfad eine zusätzliche Abhängigkeit hinzuzufügen. Nach einigen Nachforschungen stellte ich fest, dass dies möglich ist , solange Sie einen generischen Supertyp haben. Dies war für mich in Ordnung, da ich mit einer DAO- Ebene mit einem generischen Ebenen-Supertyp arbeitete. Wenn dies zu Ihrem Szenario passt, ist es meiner Meinung nach der beste Ansatz.
Die meisten Anwendungsfälle für Generika, auf die ich gestoßen bin, haben einen generischen Supertyp, z. B. List<T>für ArrayList<T>oder GenericDAO<T>für DAO<T>usw.
Mein Projekt verwendete Spring, was sogar noch besser ist, da Spring eine praktische Dienstprogrammmethode zum Finden des Typs hat. Dies ist der beste Ansatz für mich, da er am besten aussieht. Ich denke, wenn Sie Spring nicht verwenden würden, könnten Sie Ihre eigene Dienstprogrammmethode schreiben.
import org.springframework.core.GenericTypeResolver;publicabstractclassAbstractHibernateDao<T extendsDomainObject>implementsDataAccessObject<T>{@AutowiredprivateSessionFactory sessionFactory;privatefinalClass<T> genericType;privatefinalString RECORD_COUNT_HQL;privatefinalString FIND_ALL_HQL;@SuppressWarnings("unchecked")publicAbstractHibernateDao(){this.genericType =(Class<T>)GenericTypeResolver.resolveTypeArgument(getClass(),AbstractHibernateDao.class);this.RECORD_COUNT_HQL ="select count(*) from "+this.genericType.getName();this.FIND_ALL_HQL ="from "+this.genericType.getName()+" t ";}
Bitte klären Sie die Bedeutung der Argumente von resolveTypeArgument
gstackoverflow
getClass () ist eine Methode von java.lang.Object, die zur Laufzeit die Klasse des bestimmten Objekts zurückgibt. Dies ist das Objekt, für das Sie den Typ auflösen möchten. AbstractHibernateDao.class ist nur der Name der Basisklasse oder Superklasse der generischen Typklassenhierarchie. Die Importanweisung ist enthalten, damit Sie die Dokumente leicht finden und selbst überprüfen können. Dies ist die Seite docs.spring.io/spring/docs/current/javadoc-api/org/…
Ben Thurley
Was ist die Federlösung mit Version 4.3.6 und höher. Es funktioniert nicht mit Feder 4.3.6.
@ AlikElzin-kilaka wird im Konstruktor mit der Spring-Klasse GenericTypeResolver initialisiert.
Ben Thurley
103
Es gibt jedoch eine kleine Lücke: Wenn Sie Ihre FooKlasse als abstrakt definieren. Das würde bedeuten, dass Sie Ihre Klasse instanziieren müssen als:
Foo<MyType> myFoo =newFoo<MyType>(){};
(Beachten Sie die doppelten Klammern am Ende.)
Jetzt können Sie den Typ von Tzur Laufzeit abrufen :
Type mySuperclass = myFoo.getClass().getGenericSuperclass();Type tType =((ParameterizedType)mySuperclass).getActualTypeArguments()[0];
Beachten Sie jedoch, dass mySuperclassdies die Oberklasse der Klassendefinition sein muss, die den endgültigen Typ für definiert T.
Es ist auch nicht sehr elegant, aber Sie müssen entscheiden, ob Sie es bevorzugen new Foo<MyType>(){}oder new Foo<MyType>(MyType.class);in Ihrem Code.
Zum Beispiel:
import java.lang.reflect.ParameterizedType;import java.lang.reflect.Type;import java.util.ArrayDeque;import java.util.Deque;import java.util.NoSuchElementException;/**
* Captures and silently ignores stack exceptions upon popping.
*/publicabstractclassSilentStack<E>extendsArrayDeque<E>{public E pop(){try{returnsuper.pop();}catch(NoSuchElementException nsee ){return create();}}public E create(){try{Type sooper = getClass().getGenericSuperclass();Type t =((ParameterizedType)sooper).getActualTypeArguments()[0];return(E)(Class.forName( t.toString()).newInstance());}catch(Exception e ){returnnull;}}}
Dann:
publicclassMain{// Note the braces...privateDeque<String> stack =newSilentStack<String>(){};publicstaticvoid main(String args[]){// Returns a new instance of String.String s = stack.pop();System.out.printf("s = '%s'\n", s );}}
Dies ist mit Sicherheit die beste Antwort hier! Für das, was es wert ist, ist dies die Strategie, die Google Guice zum Binden von Klassen mitTypeLiteral
ATG
14
Beachten Sie, dass jedes Mal, wenn diese Methode der Objektkonstruktion verwendet wird, eine neue anonyme Klasse erstellt wird. Mit anderen Worten, zwei Objekte aund berstellt diese Weise werden beide die gleiche Klasse erweitern, haben aber nicht identische Instanz Klassen. a.getClass() != b.getClass()
Martin Serrano
3
Es gibt ein Szenario, in dem dies nicht funktioniert. Wenn Foo eine Schnittstelle wie Serializable implementieren sollte, wäre die anonyme Klasse nur dann serialisierbar, wenn die Klasse instanziiert. Ich habe versucht, dies zu umgehen, indem ich eine serialisierbare Factory-Klasse erstellt habe, die die von Foo abgeleitete anonyme Klasse erstellt. Aus irgendeinem Grund gibt getActualTypeArguments jedoch den generischen Typ anstelle der tatsächlichen Klasse zurück. Zum Beispiel: (neue FooFactory <MyType> ()). CreateFoo ()
Lior Chaga
38
Ein Standardansatz / eine Problemumgehung / eine Standardlösung besteht darin class, den Konstruktoren ein Objekt hinzuzufügen , wie z.
publicclassFoo<T>{privateClass<T> type;publicFoo(Class<T> type){this.type = type;}publicClass<T> getType(){return type;}public T newInstance(){return type.newInstance();}}
Aber es schien nicht @autowired in der tatsächlichen Verwendung, eine Möglichkeit, um zu umgehen?
Alfred Huang
@AlfredHuang Die Lösung besteht darin, eine Bean für die Klasse zu erstellen, die dies tut, und sich nicht auf das automatische Verdrahten zu verlassen.
Calebj
20
Stellen Sie sich vor, Sie haben eine abstrakte Oberklasse, die generisch ist:
publicabstractclassFoo<?extends T>{}
Und dann haben Sie eine zweite Klasse, die Foo mit einem generischen Balken erweitert, der T erweitert:
publicclassSecondextendsFoo<Bar>{}
Sie können die Klasse Bar.classin der Foo-Klasse erhalten, indem Sie die Type(aus der Antwort von bert bruynooghe) auswählen und mithilfe der folgenden ClassInstanz ableiten :
Type mySuperclass = myFoo.getClass().getGenericSuperclass();Type tType =((ParameterizedType)mySuperclass).getActualTypeArguments()[0];//Parse it as StringString className = tType.toString().split(" ")[1];Class clazz =Class.forName(className);
Sie müssen beachten, dass diese Operation nicht ideal ist. Daher empfiehlt es sich, den berechneten Wert zwischenzuspeichern, um Mehrfachberechnungen zu vermeiden. Eine der typischen Anwendungen ist die generische DAO-Implementierung.
toString().split(" ")[1]das war das Problem, vermeiden Sie die"class "
IgniteCoders
16
Hier ist eine funktionierende Lösung:
@SuppressWarnings("unchecked")privateClass<T> getGenericTypeClass(){try{String className =((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0].getTypeName();Class<?> clazz =Class.forName(className);return(Class<T>) clazz;}catch(Exception e){thrownewIllegalStateException("Class is not parametrized with generic type!!! Please use extends <> ");}}
HINWEISE:
Kann nur als Oberklasse verwendet werden
Muss mit typed class ( Child extends Generic<Integer>) erweitert werden
ODER
Muss als anonyme Implementierung erstellt werden ( new Generic<Integer>() {};)
Eine bessere Route als die von den anderen vorgeschlagene Klasse besteht darin, ein Objekt zu übergeben, das das kann, was Sie mit der Klasse getan hätten, z. B. eine neue Instanz zu erstellen.
interfaceFactory<T>{
T apply();}<T>voidList<T> make10(Factory<T> factory){List<T> result =newArrayList<T>();for(int a =0; a <10; a++)
result.add(factory.apply());return result;}classFooFactory<T>implementsFactory<Foo<T>>{publicFoo<T> apply(){returnnewFoo<T>();}}List<Foo<Integer>> foos = make10(newFooFactory<Integer>());
@ Ricky Clarkson: Ich sehe nicht ein, wie diese Fabrik parametrisierte Foos zurückgeben soll. Könnten Sie bitte erklären, wie Sie Foo <T> daraus machen? Es scheint mir, dass dies nur nicht parametrisiertes Foo ergibt. Ist das T in make10 hier nicht einfach Foo?
ib84
@ ib84 Ich habe den Code behoben. Ich habe anscheinend übersehen, dass Foo parametrisiert wurde, als ich die Antwort ursprünglich schrieb.
Ricky Clarkson
9
Ich hatte dieses Problem in einer abstrakten generischen Klasse. In diesem speziellen Fall ist die Lösung einfacher:
Ja, aber ich möchte ein Minimum belassen, das bei der Erweiterung dieser Klasse getan werden muss. Überprüfen Sie die Antwort von
Droidpl
5
Ich habe eine (hässliche, aber effektive) Lösung für dieses Problem, die ich kürzlich verwendet habe:
import java.lang.reflect.TypeVariable;publicstatic<T>Class<T> getGenericClass(){
__<T> ins =new __<T>();TypeVariable<?>[] cls = ins.getClass().getTypeParameters();return(Class<T>)cls[0].getClass();}privatefinalclass __<T>// generic helper class which does only provide type information{private __(){}}
Ich habe einen generischen und einfachen Weg gefunden, dies zu tun. In meiner Klasse habe ich eine Methode erstellt, die den generischen Typ entsprechend seiner Position in der Klassendefinition zurückgibt. Nehmen wir eine Klassendefinition wie diese an:
publicclassMyClass<A, B, C>{}
Erstellen wir nun einige Attribute, um die Typen beizubehalten:
publicclassMyClass<A, B, C>{privateClass<A> aType;privateClass<B> bType;privateClass<C> cType;// Getters and setters (not necessary if you are going to use them internally)}
Anschließend können Sie eine generische Methode erstellen, die den Typ basierend auf dem Index der generischen Definition zurückgibt:
/**
* Returns a {@link Type} object to identify generic types
* @return type
*/privateType getGenericClassType(int index){// To make it use generics without supplying the class typeType type = getClass().getGenericSuperclass();while(!(type instanceofParameterizedType)){if(type instanceofParameterizedType){
type =((Class<?>)((ParameterizedType) type).getRawType()).getGenericSuperclass();}else{
type =((Class<?>) type).getGenericSuperclass();}}return((ParameterizedType) type).getActualTypeArguments()[index];}
Schließlich rufen Sie im Konstruktor einfach die Methode auf und senden den Index für jeden Typ. Der vollständige Code sollte folgendermaßen aussehen:
publicclassMyClass<A, B, C>{privateClass<A> aType;privateClass<B> bType;privateClass<C> cType;publicMyClass(){this.aType =(Class<A>) getGenericClassType(0);this.bType =(Class<B>) getGenericClassType(1);this.cType =(Class<C>) getGenericClassType(2);}/**
* Returns a {@link Type} object to identify generic types
* @return type
*/privateType getGenericClassType(int index){Type type = getClass().getGenericSuperclass();while(!(type instanceofParameterizedType)){if(type instanceofParameterizedType){
type =((Class<?>)((ParameterizedType) type).getRawType()).getGenericSuperclass();}else{
type =((Class<?>) type).getGenericSuperclass();}}return((ParameterizedType) type).getActualTypeArguments()[index];}}
Wie in anderen Antworten erklärt, um dies zu verwenden ParameterizedType , müssen Sie die Klasse erweitern, Ansatz scheint jedoch zusätzliche Arbeit zu sein, um eine ganz neue Klasse zu erstellen, die sie erweitert ...
Wenn Sie die Klasse abstrakt machen, müssen Sie sie erweitern, um die Unterklassenanforderungen zu erfüllen. (mit @Getter von lombok).
Nun, um es zu erweitern, ohne eine neue Klasse zu definieren. (Beachten Sie das {} am Ende ... erweitert, aber überschreiben Sie nichts - es sei denn, Sie möchten).
public<T> T yourMethodSignature(Class<T> type){// get some object and check the type match the given typeObject result =...if(type.isAssignableFrom(result.getClass())){return(T)result;}else{// handle the error}}
Wenn Sie eine Klasse / Schnittstelle erweitern oder implementieren, die Generika verwendet, erhalten Sie möglicherweise den generischen Typ der übergeordneten Klasse / Schnittstelle, ohne eine vorhandene Klasse / Schnittstelle zu ändern.
Es könnte drei Möglichkeiten geben,
Fall 1
Wenn Ihre Klasse eine Klasse erweitert, die Generics verwendet
Das ist ziemlich einfach. Wenn Sie aus derselben Klasse benötigen:
Class clazz =this.getClass();ParameterizedType parameterizedType =(ParameterizedType) clazz.getGenericSuperclass();try{Class typeClass =Class.forName( parameterizedType.getActualTypeArguments()[0].getTypeName());// You have the instance of type 'T' in typeClass variableSystem.out.println("Class instance name: "+ typeClass.getName());}catch(ClassNotFoundException e){System.out.println("ClassNotFound!! Something wrong! "+ e.getMessage());}
Ich nehme an, Sie haben ein Feld in Ihrer Klasse vom Typ T. Wenn es kein Feld vom Typ T gibt, was bringt es, einen generischen Typ zu haben? Sie können also einfach eine Instanz von in diesem Feld ausführen.
In meinem Fall habe ich eine
<T> Elemente auflisten;
in meiner Klasse, und ich überprüfe, ob der Klassentyp "Lokalität" von ist
if (items.get (0) Instanz der Lokalität) ...
Dies funktioniert natürlich nur, wenn die Gesamtzahl der möglichen Klassen begrenzt ist.
classGenericClass<T>(private val rawType:Class<*>){
constructor():this(`$Gson$Types`.getRawType(object :TypeToken<T>(){}.getType()))
fun getRawType():Class<T>{return rawType as Class<T>}}
Ich wollte T.class an eine Methode übergeben, die Generika verwendet
Die Methode readFile liest eine durch den Dateinamen angegebene CSV-Datei mit dem vollständigen Pfad. Es kann CSV-Dateien mit unterschiedlichen Inhalten geben, daher muss ich die Modelldateiklasse übergeben, damit ich die entsprechenden Objekte erhalten kann. Da dies das Lesen einer CSV-Datei ist, wollte ich dies generisch tun. Aus irgendeinem Grund hat keine der oben genannten Lösungen für mich funktioniert. Ich muss es verwenden
Class<? extends T> type, damit es funktioniert. Ich benutze die opencsv-Bibliothek zum Parsen der CSV-Dateien.
import com.fasterxml.jackson.core.type.TypeReference;
new TypeReference<T>(){}
Antworten:
Die kurze Antwort lautet, dass es in Java keine Möglichkeit gibt, den Laufzeittyp generischer Typparameter herauszufinden. Ich empfehle, das Kapitel über das Löschen von Typen im Java-Lernprogramm zu lesen, um weitere Informationen zu erhalten.
Eine beliebte Lösung hierfür besteht darin, den
Class
Parameter type vom Typ an den Konstruktor des generischen Typs zu übergeben, zquelle
typeParameterClass
ohne Standardzuweisung im Konstruktor ist vollkommen in Ordnung. Es ist nicht erforderlich, es ein zweites Mal einzustellen.Ich suchte nach einer Möglichkeit, dies selbst zu tun, ohne dem Klassenpfad eine zusätzliche Abhängigkeit hinzuzufügen. Nach einigen Nachforschungen stellte ich fest, dass dies möglich ist , solange Sie einen generischen Supertyp haben. Dies war für mich in Ordnung, da ich mit einer DAO- Ebene mit einem generischen Ebenen-Supertyp arbeitete. Wenn dies zu Ihrem Szenario passt, ist es meiner Meinung nach der beste Ansatz.
Die meisten Anwendungsfälle für Generika, auf die ich gestoßen bin, haben einen generischen Supertyp, z. B.
List<T>
fürArrayList<T>
oderGenericDAO<T>
fürDAO<T>
usw.Reine Java-Lösung
Der Artikel Zugriff auf generische Typen zur Laufzeit in Java erklärt, wie Sie dies mit reinem Java tun können.
Federlösung
Mein Projekt verwendete Spring, was sogar noch besser ist, da Spring eine praktische Dienstprogrammmethode zum Finden des Typs hat. Dies ist der beste Ansatz für mich, da er am besten aussieht. Ich denke, wenn Sie Spring nicht verwenden würden, könnten Sie Ihre eigene Dienstprogrammmethode schreiben.
quelle
Es gibt jedoch eine kleine Lücke: Wenn Sie Ihre
Foo
Klasse als abstrakt definieren. Das würde bedeuten, dass Sie Ihre Klasse instanziieren müssen als:(Beachten Sie die doppelten Klammern am Ende.)
Jetzt können Sie den Typ von
T
zur Laufzeit abrufen :Beachten Sie jedoch, dass
mySuperclass
dies die Oberklasse der Klassendefinition sein muss, die den endgültigen Typ für definiertT
.Es ist auch nicht sehr elegant, aber Sie müssen entscheiden, ob Sie es bevorzugen
new Foo<MyType>(){}
odernew Foo<MyType>(MyType.class);
in Ihrem Code.Zum Beispiel:
Dann:
quelle
TypeLiteral
a
undb
erstellt diese Weise werden beide die gleiche Klasse erweitern, haben aber nicht identische Instanz Klassen.a.getClass() != b.getClass()
Ein Standardansatz / eine Problemumgehung / eine Standardlösung besteht darin
class
, den Konstruktoren ein Objekt hinzuzufügen , wie z.quelle
Stellen Sie sich vor, Sie haben eine abstrakte Oberklasse, die generisch ist:
Und dann haben Sie eine zweite Klasse, die Foo mit einem generischen Balken erweitert, der T erweitert:
Sie können die Klasse
Bar.class
in der Foo-Klasse erhalten, indem Sie dieType
(aus der Antwort von bert bruynooghe) auswählen und mithilfe der folgendenClass
Instanz ableiten :Sie müssen beachten, dass diese Operation nicht ideal ist. Daher empfiehlt es sich, den berechneten Wert zwischenzuspeichern, um Mehrfachberechnungen zu vermeiden. Eine der typischen Anwendungen ist die generische DAO-Implementierung.
Die endgültige Implementierung:
Der zurückgegebene Wert ist Bar.class, wenn er von der Foo-Klasse in einer anderen Funktion oder von der Bar-Klasse aufgerufen wird.
quelle
toString().split(" ")[1]
das war das Problem, vermeiden Sie die"class "
Hier ist eine funktionierende Lösung:
HINWEISE: Kann nur als Oberklasse verwendet werden
Child extends Generic<Integer>
) erweitert werdenODER
new Generic<Integer>() {};
)quelle
Sie können dies aufgrund der Typlöschung nicht tun. Siehe auch Frage zum Stapelüberlauf Java-Generika - Löschen vom Typ - wann und was passiert .
quelle
Eine bessere Route als die von den anderen vorgeschlagene Klasse besteht darin, ein Objekt zu übergeben, das das kann, was Sie mit der Klasse getan hätten, z. B. eine neue Instanz zu erstellen.
quelle
Ich hatte dieses Problem in einer abstrakten generischen Klasse. In diesem speziellen Fall ist die Lösung einfacher:
und später die abgeleitete Klasse:
quelle
Ich habe eine (hässliche, aber effektive) Lösung für dieses Problem, die ich kürzlich verwendet habe:
quelle
Es ist möglich:
Sie benötigen zwei Funktionen von hibernate-generic-dao / blob / master / dao / src / main / java / com / googlecode / genericdao / dao / DAOUtil.java .
Weitere Erklärungen finden Sie unter Reflektieren von Generika .
quelle
Ich habe einen generischen und einfachen Weg gefunden, dies zu tun. In meiner Klasse habe ich eine Methode erstellt, die den generischen Typ entsprechend seiner Position in der Klassendefinition zurückgibt. Nehmen wir eine Klassendefinition wie diese an:
Erstellen wir nun einige Attribute, um die Typen beizubehalten:
Anschließend können Sie eine generische Methode erstellen, die den Typ basierend auf dem Index der generischen Definition zurückgibt:
Schließlich rufen Sie im Konstruktor einfach die Methode auf und senden den Index für jeden Typ. Der vollständige Code sollte folgendermaßen aussehen:
quelle
Wie in anderen Antworten erklärt, um dies zu verwenden
ParameterizedType
, müssen Sie die Klasse erweitern, Ansatz scheint jedoch zusätzliche Arbeit zu sein, um eine ganz neue Klasse zu erstellen, die sie erweitert ...Wenn Sie die Klasse abstrakt machen, müssen Sie sie erweitern, um die Unterklassenanforderungen zu erfüllen. (mit @Getter von lombok).
Nun, um es zu erweitern, ohne eine neue Klasse zu definieren. (Beachten Sie das {} am Ende ... erweitert, aber überschreiben Sie nichts - es sei denn, Sie möchten).
quelle
Ich gehe davon aus, dass Sie, da Sie eine generische Klasse haben, eine solche Variable haben würden:
(Diese Variable muss im Konstruktor einen Wert annehmen.)
In diesem Fall können Sie einfach die folgende Methode erstellen:
Ich hoffe es hilft!
quelle
quelle
Wenn Sie eine Klasse / Schnittstelle erweitern oder implementieren, die Generika verwendet, erhalten Sie möglicherweise den generischen Typ der übergeordneten Klasse / Schnittstelle, ohne eine vorhandene Klasse / Schnittstelle zu ändern.
Es könnte drei Möglichkeiten geben,
Fall 1 Wenn Ihre Klasse eine Klasse erweitert, die Generics verwendet
Fall 2 Wenn Ihre Klasse eine Schnittstelle implementiert, die Generics verwendet
Fall 3 Wenn Ihre Schnittstelle eine Schnittstelle erweitert, die Generika verwendet
quelle
Das ist ziemlich einfach. Wenn Sie aus derselben Klasse benötigen:
quelle
Ich nehme an, Sie haben ein Feld in Ihrer Klasse vom Typ T. Wenn es kein Feld vom Typ T gibt, was bringt es, einen generischen Typ zu haben? Sie können also einfach eine Instanz von in diesem Feld ausführen.
In meinem Fall habe ich eine
in meiner Klasse, und ich überprüfe, ob der Klassentyp "Lokalität" von istDies funktioniert natürlich nur, wenn die Gesamtzahl der möglichen Klassen begrenzt ist.
quelle
Diese Frage ist alt, aber jetzt ist es am besten, Google zu verwenden
Gson
.Ein Beispiel, um benutzerdefinierte zu erhalten
viewModel
.Generische Typklasse
quelle
Ich wollte T.class an eine Methode übergeben, die Generika verwendet
Die Methode readFile liest eine durch den Dateinamen angegebene CSV-Datei mit dem vollständigen Pfad. Es kann CSV-Dateien mit unterschiedlichen Inhalten geben, daher muss ich die Modelldateiklasse übergeben, damit ich die entsprechenden Objekte erhalten kann. Da dies das Lesen einer CSV-Datei ist, wollte ich dies generisch tun. Aus irgendeinem Grund hat keine der oben genannten Lösungen für mich funktioniert. Ich muss es verwenden
Class<? extends T> type
, damit es funktioniert. Ich benutze die opencsv-Bibliothek zum Parsen der CSV-Dateien.So wird die readFile-Methode aufgerufen
quelle
Ich verwende eine Problemumgehung dafür:
quelle