2010-02-16 20 views
5

La mayor parte de la documentación relacionada con el manejo de borrado de tipos en Java asume que el caso de uso maneja un tipo como SomeType<ParamType>. que estoy tratando de procesar el parámetro método para el siguiente método:Java: obtención de tipo interno en tipos parametrizados anidados (reflexión)

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

Cuando la clase de contenedor se crea una instancia de un tipo DvQuantity, esta firma debe convertirse en public void setOtherReferenceRanges(List<ReferenceRange<DvQuanitity>> referenceRanges) en tiempo de ejecución.

Usando la reflexión uno puede ver que el List tiene un actualTypeArgument que es ReferenceRange<T>. Como la reflexión usa información de clase, no esperaría que me dé ReferenceRange<DvQuantity>. Sin embargo, cuando creé la clase que contenía este método, pasé el tipo DvQuantity como T. Por lo tanto, el tipo de relleno en T debe estar disponible para el tiempo de ejecución de Java, pero no pude encontrar la manera de obtenerlo. Termino con un objeto TypeVariableImpl al que se accede a través de la reflexión, que no parece contener ningún dato útil.

¿Puede encontrar alguna forma de descubrir esta información en tiempo de ejecución?

Respuesta

1

Cuando dice

cuando creé la clase que contiene este método

supongo que quiere decir cuando se crea un objeto de ese tipo, por ejemplo:

foo = new ContainerClass<DvQuantity>(); 

En ese caso, debido a la eliminación, no hay forma de recuperar el tipo DvQuantity.

Sin embargo, si crea una clase pasar un parámetro de tipo a la superclase, como este

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

O, más corto, una subclase anónima en línea (que se ve casi como el primer ejemplo, pero con una sutil pero importante diferencia):

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

a continuación, puede recuperar el parámetro de tipo, debido a que se recupere el parámetro de tipo utilizado para extender una superclase en tiempo de ejecución. Por desgracia, Java en sí no proporciona una manera fácil de obtener ahora el tipo del método DvQuantityContainerClass.setOtherReferenceRanges con el T rellenado Para ello, he escrito gentyref, hacer reflexión avanzada sobre los tipos genéricos:.

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

Gracias por la respuesta. Valida lo que he visto hasta ahora. Lamentablemente, no tengo poder sobre la configuración en la que necesito hacer que esto funcione. También gracias a otras respuestas, todas las cuales serían útiles si tuviera control sobre la situación. – mahonya

0

La información del tipo genérico es erased by the compiler y no está disponible en tiempo de ejecución. Cuando necesito para asegurar un cierto tipo en tiempo de ejecución que pase en un argumento de clase:

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

Esto siempre no es conveniente ni posible, pero para muchos casos es posible.

0

Por lo tanto, el relleno de tipo T debe estar disponible para el tiempo de ejecución de Java, pero no pude encontrar la manera de obtenerlo.

quizás no es del todo correcto, pero la forma en que pienso en ello es que en tiempo de ejecución no existe una clase real - sólo un objeto sin un tipo específico que se reúne la interfaz de T. En otras palabras, el borrado no sucede con objetos, pero en cambio con estas nebulosas (al menos en el mundo OOP) tipo-cosas.

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

Hay formas de capturar la información de tipo dentro de la propia clase (tipo T necesitarían un método getUnderlyingType() ... o algo así), pero eso es una mala idea. Si realmente necesita el tipo sin procesar del objeto, reconsideraría el uso de genéricos.

Cuestiones relacionadas