J'ai un cours abstrait:
public abstract class RootProcessor<T> {
Class<T> clazz;
}
J'ai besoin de remplir ClassT clazz;
avec les enfants de RootProcessor
- chaque enfant a son propre T
J'ai trouvé une seule solution, mais il faut l'argument du compilateur -Xlint:unchecked
public RootProcessor(){
this.clazz = (Class<T>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
}
Est-ce la meilleure solution? Peut-on faire la même chose sans -Xlint:unchecked
?
Pour ce faire, il faut passer le Class<T>
jeton "où le compilateur peut le voir":
public abstract class RootProcessor<T> {
Class<T> clazz;
protected RootProcessor<T>(Class<T> clazz) {
this.clazz = clazz;
}
}
public class FooProcessor extends RootProcessor<Foo> {
public FooProcessor() {
super(Foo.class);
}
}
Si vous réalisez une distribution non contrôlée, mais que vous "savez ce que vous faites" et que vous voulez que le compilateur arrête de se plaindre, la bonne approche consiste à localiser les bits non sécurisés au niveau du type, mais vous savez qu'ils fonctionnent. en utilisant @SuppressWarnings
:
public abstract class RootProcessor<T> {
Class<T> clazz;
{ initClazz(); }
@SuppressWarnings("unchecked")
private void initClazz() {
// the usual verbiage you already have in your question
this.clazz = this.getClass().getGenericSuperclass().yadda().blah();
}
}
(Je ne t'en voudrai pas: P)
Il y a un article du même sujet: Reflecting generics
Et une classe qui l'implémente: TypeArgumentsUtils.Java
Un exemple est dans le test unitaire.
Donc si vous avez ce cours:
public class BarProcessor extends RootProcessor<Bar> {
public BarProcessor() {
}
}
que vous obtiendriez le premier paramètre avec:
Class barClass = TypeArgumentsUtils.getFirstTypeArgument(
RootProcessor.class, BarProcessor.class);