49

我有一个抽象类:

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

我需要ClassT clazz;用孩子们来填充RootProcessor——每个孩子都有自己的T

我只找到了一种解决方案,但它需要编译器参数-Xlint:unchecked

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

这是最好的解决方案吗?我们可以不做同样的事情-Xlint:unchecked吗?

4

2 回答 2

39

执行此操作的类型安全但样板化的方法是传递Class<T>标记“编译器可以看到的地方”:

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

如果您正在执行未经检查的强制转换,但您“知道自己在做什么”并且希望编译器停止抱怨,那么正确的方法是本地化非类型安全但您知道它们的工作位和使用@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();
    }
}

(我不会反对你:P)

于 2013-05-28T18:55:11.997 回答
3

有一个相同主题的帖子:Reflecting generics

还有一个实现它的类:TypeArgumentsUtils.java

一个例子是在单元测试中。

所以如果你有这个类:

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

比你得到的第一个参数:

Class barClass = TypeArgumentsUtils.getFirstTypeArgument(
        RootProcessor.class, BarProcessor.class);
于 2015-06-09T15:40:05.137 回答