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 1:

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)

Solution 2:

There is a post of the same subject: Reflecting generics

And a class that implement it:TypeArgumentsUtils.java

An example is in the unit test.

So if you have this class:

public class BarProcessor extends RootProcessor<Bar> {
    public BarProcessor() {
    }
}

than you would get the first parameter with:

Class barClass = TypeArgumentsUtils.getFirstTypeArgument(
        RootProcessor.class, BarProcessor.class);