Malheureusement, Christoph solution comme l'écrit ne fonctionne que dans des circonstances très limitées. Notez que cela ne fonctionne que dans les classes abstraites, tout d'abord. L'autre difficulté, c'est qu' g()
seulement des œuvres à partir des sous-classes DIRECTES de A
. Nous pouvons résoudre ce problème, cependant:
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);
}
Ceci fonctionne dans beaucoup de situations dans la pratique, mais pas TOUT le temps. Considérer:
public class Foo<U,T extends Collection<?>> extends A<T> {}
(new Foo<String,List<Object>>() {}).g();
Cela permettra de jeter un ClassCastException
, parce que le type de l'argument ici n'est pas un Class
ou ParameterizedType
; c'est l' TypeVariable
T
. Alors maintenant, vous seriez coincé à essayer de comprendre à quel type T
était censé reposer, et ainsi de suite vers le bas le trou de lapin.
Je pense que la seule raisonnable, de manière générale, la réponse est quelque chose qui s'apparente à Nicolas initiale de la réponse -- en général, si vos besoins de la classe à instancier des objets de la classe qui est inconnu au moment de la compilation, les utilisateurs de votre classe a besoin de passer que la classe littérale (ou, peut-être, une Usine) de votre classe explicitement et ne pas compter uniquement sur les médicaments génériques.