2010-02-16 24 views
5

La maggior parte della documentazione relativa alla gestione della cancellazione dei tipi in Java presuppone che il caso d'uso stia gestendo un tipo come SomeType<ParamType>. Sto cercando di elaborare parametro del metodo per il metodo seguente:Java: acquisizione del tipo interno in tipi parametrici nidificati (riflessione)

public void setOtherReferenceRanges(List<ReferenceRange<T>> referenceRanges) 

Quando la classe contenitore è un'istanza con un tipo DvQuantity, questa firma dovrebbe diventare public void setOtherReferenceRanges(List<ReferenceRange<DvQuanitity>> referenceRanges) in fase di esecuzione.

Utilizzando la riflessione si può vedere che lo List ha uno actualTypeArgument che è ReferenceRange<T>. Dal momento che la riflessione utilizza le informazioni di classe, non mi aspetto che mi dia ReferenceRange<DvQuantity>. Tuttavia, quando ho creato la classe contenente questo metodo, ho passato il tipo DvQuantity come T. Quindi il tipo che compila T dovrebbe essere disponibile per il runtime Java, ma non sono riuscito a trovare un modo per ottenerlo. Finisco con un oggetto TypeVariableImpl a cui si accede tramite la riflessione, che non sembra contenere dati utili.

Riesci a pensare a qualche modo per scoprire queste informazioni in runtime?

risposta

1

Quando si dice

quando ho creato la classe che contiene questo metodo

Credo che si intende quando si crea un oggetto di quel tipo, per esempio:

foo = new ContainerClass<DvQuantity>(); 

In tal caso, a causa della cancellazione, non è possibile ripristinare il tipo DvQuantity.

Tuttavia, se si crea una classe passando un parametro di tipo alla superclasse, come questo

class DvQuantityContainerClass extends ContainerClass<DvQuantity> {...} 
... 
foo = new DvQuantityContainerClass(); 

Oppure, più breve, una sottoclasse anonima in linea (che sembra quasi come il primo esempio, ma con una sottile ma importante differenza):

foo = new ContainerClass<DvQuantity>(){}; 

Poi si può recuperare il parametro di tipo, perché si recupera il parametro di tipo utilizzato per estendere una superclasse in fase di esecuzione. Purtroppo, Java stesso non fornisce un modo semplice per ora ottenere il tipo del metodo DvQuantityContainerClass.setOtherReferenceRanges con il T compilato Per questo, ho scritto gentyref, fare riflessione avanzata su tipi generici:.

Method m = DvQuantityContainerClass.class.getMethod("setOtherReferenceRanges", List.class); 
// this will return List<ReferenceRange<DvQuanity>>, like you are lookingn for 
return GenericTypeReflector.getExactParameterTypes(m, DvQuantityContainerClass.class) 
+0

Grazie per la risposta. Convalida ciò che ho visto finora. Sfortunatamente non ho alcun potere sul setup in cui ho bisogno di fare questo lavoro. Anche grazie ad altre risposte, tutte utili se avessi il controllo della situazione. – mahonya

0

Le informazioni di tipo generico sono erased by the compiler e non sono disponibili in fase di esecuzione. Quando ho bisogno per garantire un certo tipo in fase di esecuzione passo in un argomento di classe:

public <T> void doSomething(T t, Class<T> c); 

Questo non è sempre conveniente o persino possibile, ma per molti casi è possibile.

0

Quindi il tipo che compila T dovrebbe essere disponibile per il runtime Java, ma non sono riuscito a trovare un modo per ottenerlo.

forse non è del tutto corretto, ma il mio modo di pensare a questo proposito è che in fase di esecuzione non esiste una categoria reale - solo un oggetto senza un tipo specifico che soddisfa l'interfaccia di T. In altre parole, la cancellazione non avviene con oggetti, ma invece con questi nebulosi (almeno nel mondo OOP) tipo-cose.

http://java.sun.com/docs/books/tutorial/java/generics/erasure.html

Ci sono modi di catturare le informazioni sul tipo all'interno della classe stessa (tipi T avrebbero bisogno di un metodo di getUnderlyingType() ... o qualcosa del genere), ma questa è una cattiva idea. Se hai veramente bisogno del tipo grezzo dell'oggetto, riconsidererei l'uso dei farmaci generici.

Problemi correlati