tipo operador objeto manejo instanciar genericos genericas generica diamante datos dato con comodin clases java generics type-erasure

operador - Obteniendo T.class a pesar del borrado de tipos de Java



tipo comodin java (5)

Estoy tratando de vincular una interfaz a su implementación como leída de un archivo de configuración para que pueda alimentarlo a mi contenedor IoC. Aquí está más o menos lo que estoy tratando de hacer:

public class PropertyImplementationBinder<T> { // ... public Class getInterfaceClass() { return T.class; // OR Class<T>, note T is not newable } public Class getImplementationClass() { return /* read config file to get implementation class */; } }

¿Es de alguna manera posible obtener T.class ?


Necesitas pasar explícitamente la clase al constructor (y almacenarla tú mismo).

private final Class<T> clazz; PropertyImplementationBinder(Class<T> clazz){ this.clazz = clazz; } public Class<T> getInterfaceClass() { return clazz; }


No, no es posible.

La única excepción al borrado de tipos de Java es que a través de la reflexión puede encontrar el tipo parametrizado a través de la reflexión en los campos de una clase.


Puede obtener los argumentos de tipo reales para una superclase genérica de una clase. Esta publicación de blog explora las posibilidades presentadas por este, incluido un pequeño truco usando clases internas anónimas triviales. Para citar directamente:

Resulta que aunque la JVM no rastreará los argumentos de tipo reales para las instancias de una clase genérica, rastrea los argumentos de tipo reales para las subclases de las clases genéricas. En otras palabras, aunque una new ArrayList<String>() es realmente una new ArrayList() en tiempo de ejecución, si una clase amplía ArrayList<String> , entonces la JVM sabe que String es el argumento de tipo real para el parámetro de tipo List .


Por cierto. El método estático de ejemplo getType en el artículo de @Richard Gomes tiene dos errores. debería ir así:

static public Class<?> getType(final Class<?> klass, final int pos) { // obtain anonymous, if any, class for ''this'' instance final Type superclass = klass.getGenericSuperclass(); // test if an anonymous class was employed during the call if ( !(superclass instanceof ParameterizedType) ) { throw new RuntimeException("This instance should belong to an anonymous class"); } // obtain RTTI of all generic parameters final Type[] types = ((ParameterizedType) superclass).getActualTypeArguments(); // test if enough generic parameters were passed if ( pos >= types.length ) { throw new RuntimeException(String.format("Could not find generic parameter #%d because only %d parameters were passed", pos, types.length)); } if (!(types[pos] instanceof Class<?>)) { throw new RuntimeException("Generic type is not a class but declaration definition(all you get is /"[T]/") " + types[pos]); } // return the type descriptor of the requested generic parameter return (Class<?>) types[pos]; }

Lamentablemente, todavía no es la bala mágica porque funciona si tienes en código explícitamente

getType(new SomeObject<String>(){}.class, 0) // you get String.class

pero si llamas esto algo así como

getType(new SomeObject<T>(){}.class, 0) // you get T as TypeVariable<D> and not actuall class of it

Solo nombre T.


Contrariamente a lo que es ampliamente aceptado y raramente conocido, se puede evitar el borrado de tipos, lo que significa que los destinatarios tienen la capacidad de saber qué parámetros genéricos se utilizaron durante la llamada.

Por favor, eche un vistazo a: Usando TypeTokens para recuperar parámetros genéricos

El artículo también habla sobre las experiencias de nuestros usuarios con la técnica. En pocas palabras, terminamos cayendo de nuevo al ...

Técnica convencional y ampliamente utilizada: "Pasar tipos de clase en constructores"