Desafortunadamente solución de Christoph tal como está escrita sólo funciona en circunstancias muy limitadas . [EDITAR: como se comenta a continuación, ya no recuerdo mi razonamiento para esta frase y es probable que esté equivocado: "Tenga en cuenta que esto solo funcionará en clases abstractas, en primer lugar."] La siguiente dificultad es que g()
solo funciona desde subclases DIRECTAS de A
. Sin embargo, podemos solucionarlo:
private Class<?> extractClassFromType(Type t) throws ClassCastException {
if (t instanceof Class<?>) {
return (Class<?>)t;
}
return (Class<?>)((ParameterizedType)t).getRawType();
}
public Class<B> g() throws ClassCastException {
Class<?> superClass = getClass(); // initial value
Type superType;
do {
superType = superClass.getGenericSuperclass();
superClass = extractClassFromType(superType);
} while (! (superClass.equals(A.class)));
Type actualArg = ((ParameterizedType)superType).getActualTypeArguments()[0];
return (Class<B>)extractClassFromType(actualArg);
}
Esto funcionará en muchas situaciones en la práctica, pero no TODO el tiempo. Considere lo siguiente:
public class Foo<U,T extends Collection<?>> extends A<T> {}
(new Foo<String,List<Object>>() {}).g();
Esto lanzará un ClassCastException
, porque el argumento de tipo aquí no es un Class
o una ParameterizedType
en absoluto; es el TypeVariable
T
. Así que ahora estarías atascado tratando de averiguar qué tipo se suponía que representaba el T
, y así sucesivamente en el agujero del conejo.
Creo que la única respuesta razonable y general es algo parecido a la respuesta inicial de Nicolas: en general, si su clase necesita instanciar objetos de otra clase desconocida en tiempo de compilación, los usuarios de su clase deben pasar esa clase literal (o, tal vez, una fábrica) para su clase de forma explícita y no depender únicamente de los genéricos.
Seguro que es feo, pero el truco del constructor protegido es suficiente para mí. Estoy usando la clase genérica como una clase abstracta que sirve como base de 5 a 10 clases concretas. ¡Gracias! –
¿Es posible usar esto para determinar qué tipo genérico es un objeto? por ejemplo, 'if (obj.getClazz() es una Cadena) doThis(); if (obj.getClazz() es un Entero) doThat(); ' – dwjohnston
^Solución: ' if (obj.getClazz(). Equals (String.class)) ... ' – dwjohnston