Search code examples
javagenerics

Java generics, get Class<T> of generic parameter


I have an abstract class:

public abstract class RootProcessor<T> {
    Class<T> clazz;
}

I need to fill ClassT clazz; with the children of RootProcessor - every child has its own T

I found only one solution, but it needs compiler argument -Xlint:unchecked

public RootProcessor(){
    this.clazz = (Class<T>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
}

Is this the best solution? Can we do the same without -Xlint:unchecked ?


Solution

  • The typesafe, but boilerplatey way to do this is to pass the Class<T> token "where the compiler can see it":

    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);
        }
    }
    

    If you're doing an unchecked cast but you "know what you're doing" and want the compiler to stop complaining, the correct approach would be localising the non-type-safe-but-you-know-they-work bits and using @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();
        }
    }
    

    (I won't hold this against you :P)