2012-05-29 13 views
9

Ich möchte generische Funktion, die Objektdarstellung des XML-Dokuments (mit JAXB) zurückgeben. Ich muss "Klasse" -Objekt an JAXBContext-Konstruktor übergeben, aber wie kann ich es von T bekommen?Get "Class" -Objekt vom generischen Typ T

public <T> readXmlToObject(String xmlFileName, T jaxbClass) { 
    JAXBContext context = JAXBContext.newInstance(T.class); // T.class - here error, how to get it? 
    ....... 
} 
+1

Suche nach 'Typ Löschung' :-) –

Antwort

13

Übergeben Sie stattdessen das Klassenobjekt und es ist einfach.

public <T> T readXmlToObject(String xmlFileName, Class<T> jaxbClass) { 
     JAXBContext context = JAXBContext.newInstance(jaxbClass); // T.class - here error, how to get it? 
     Object o = context.createUnmarshaller().unmarshal(new File(xmlFileName)); 
     return jaxbClass.cast(o); 
} 

Die Idee dabei ist, dass, da Sie nicht die Typ-Parameter aus dem Objekt extrahieren, können Sie es in die andere Richtung zu tun haben, um: mit der Klasse beginnen und dann manipulieren, um das Objekt der Typ-Parameter übereinstimmen.

+0

(Ich glaube nicht, dass die '? Erweitert' kauft dir hier irgendwas.) –

+0

@ TomHawtin-tackline Du hast Recht. – biziclop

3

Sie können die Klasse nicht zur Laufzeit erhalten. Java implementiert Generics mit Type Safe Erasure, was bedeutet, dass das Verständnis des Generic-Typs nur bei der Kompilierung angewendet wird. Sie müssen das tatsächliche Objekt zur Laufzeit abfragen, wenn Sie seine Klasse abrufen möchten.

+2

-1 Falsch! Die Klasse wird übergeben. Das Problem ist mit der Methodensignatur – Bohemian

+1

Danke für die Eingabe. Wie geschrieben, würde es nicht funktionieren, aber ich sehe Ihren Punkt darin, die Eingabe in Klasse anstelle von T zu ändern. Das wäre in Ordnung. Es wäre aber nett, wenn es nicht einmal wegen Javas schlechter Generika impl wäre. –

+0

Ich habe meinen Downvote entfernt - deine Antwort ist nicht * das * falsch :) – Bohemian

1

Werfen Sie einen Blick auf this SO answer.

Grundsätzlich ist der Typ T zur Laufzeit nicht verfügbar - Java Generics unterliegen erasure by the compiler.

Glücklicherweise haben Sie bereits eine Instanz der Klasse, so dass Sie die Typinformationen von dort bekommen können:

public <T> readXmlToObject(String xmlFileName, T jaxbClass) { 

    // if jaxbClass is an instance of the data object, you can do this: 
    JAXBContext context = JAXBContext.newInstance(jaxbClass.getClass()); 

    // alternatively if jaxbClass is an instance of the Class object: 
    JAXBContext context = JAXBContext.newInstance(jaxbClass); 
    // ...... 
} 
+0

-1 Total wird nicht funktionieren. 'jaxbClass.getClass()' gibt 'Class.class' zurück. Und du irrst dich auch - Löschen ist hier kein Problem, weil die Klasse übergeben wird. – Bohemian

+0

ah - ich nahm an, dass es eine Instanz der Klasse war (wenn man es bekommt, weil es auf T und nicht auf Klasse beschränkt war) mein Drift ...) –

+0

Ich bekomme dich, aber denke, das ist sein Problem - er hat den falschen Typ für den Parameter codiert. Er * gibt kein * T 'weiter, weil er nach dem Aufruf keine Instanz von' T 'hat, aber er kann eine Instanz von' Class 'übergeben. Ich gebe zu, ich gehe mit dem Parameternamen 'jaxbClass', was ziemlich stark darauf hindeutet, dass es eine' Klasse' ist. – Bohemian

1

versuchen, die Klasse selbst, so etwas wie dieser

public <T> readXmlToObject(String xmlFileName, Class<T> class) { 
6

Don passieren‘ hör auf die anderen ... du kannst es bekommen.

einfach den Typ des zu Class<T>jaxbClass Parameter ändern:

public <T> T readXmlToObject(String xmlFileName, Class<T> jaxbClass) { 
    JAXBContext context = JAXBContext.newInstance(jaxbClass); 
    ....... 
} 
0
public class XYZ<T> { 
    ... 
    private Class<T> tClass;  
    ... 
    public <T> readXmlToObject(String xmlFileName) { 
     JAXBContext context = JAXBContext.newInstance(tClass); 
     ... 
    } 
    ... 
} 
+0

Ich glaube nicht, dass das funktionieren wird, weil tClass wird nicht initialisiert und Sie übergeben eine Null an den Aufruf "JAXBContext.newInstance (..)". –

+0

Sie haben Recht, @ go-rose-hulman. –

+1

In meinem Code habe ich es so gemacht: private Klasse entityClass; final ParameterizedType type = (ParametrierterTyp) getClass(). getGenericSuperclass(); entityClass = (Klasse ) type.getActualTypeArguments() [0]; –

Verwandte Themen