Java泛型,获取泛型参数的Class<T>

52

我有一个抽象类:

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来实现相同的效果?


5
如需进行不安全的强制类型转换,请尽可能地局部使用 @SuppressWarnings,而不要使用 -Xlint:unchecked - millimoose
4
没错,如果编译器无法从头到尾跟踪T的类型,则无法在运行时安全地获取Class<T>。这里既保证了类型安全,又有点啰嗦,可以采用引入一个以clazz为参数的受保护构造函数的方法。 - millimoose
@millimoose: 你为什么不把它写成一个答案?我很少有什么可以补充的了;-) - meriton
是的,这是一个很好的答案。我认为带参数的构造函数是一个很好的解决方案。对于这个问题来说,它是一个简单的答案))) - Victor Mezrin
例如:key = gson.fromJson(json, key.getClass().getGenericSuperclass()); 可以修复 key = gson.fromJson(json,HashMap.class); - User8461
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)


3

有一个相同主题的帖子:反射泛型

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

单元测试中有一个示例。

所以如果你有这个类:

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

如果您想获取第一个参数,可以使用以下代码:

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

第二个链接已经失效。 - nasch
这是缺失的链接吗:http://grepcode.com/file/repo1.maven.org/maven2/de.alpharogroup/jaulp.lang/3.11.0/de/alpharogroup/lang/TypeArgumentsUtils.java - Lee Meador

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接