假设我正在保留某个类的子类的注册表,T
:
public class ClassRegistry<T> {
Set<Class<? extends T>> klasses;
...
public void register(Class<? extends T> klass) {
klasses.add(klass);
}
您通过类似 registry.register(this.getClass())
的电话注册自己.我想使用 ClassRegistry<T>
上的方法使这更简单你自己过去的地方,this
,例如 registry.register(this)
:
public void register(Object obj) {
Class<?> klass = obj.getClass();
this.register(klass);
}
糟糕,这是错误的,因为它会调用自身(将重载与参数类型匹配 Object
而不是,当然, Class<? extends T>
)。所以,相反:
public void register(Object obj) {
Class<? extends T> klass = obj.getClass();
this.register(klass);
}
现在当然不能编译了,因为编译器不知道你的 obj
实际上是某种类型 ? extends T
.它可能不会,因为调用者可能是错误的。
所以我的问题是:如何测试/验证 obj
是 T
的子类这是一个通配符上限(所以我可以安全地转换)? (我怀疑 - 或者也许希望 - 答案涉及 Guava 的 TypeToken
,这就是我添加 Guava 标签的原因,但我会接受任何答案,谢谢!)
最佳答案
你不应该能够注册任何类型的任何对象,这就是类型 Object
意味着你的 register
方法。
我会将该参数的类型更改为 T
.然后,你可以保证 obj.getClass()
将返回 Class<? extends T>
.编译器不会完全同意这一点,因为 Javadocs for getClass()
状态:
The actual result type is Class where |X| is the erasure of the static type of the expression on which getClass is called.
调用 getClass()
的结果不是 Class<? extends T>
,但是 Class<? extends Object>
(删除 T
)。您可以将其转换为 Class<? extends T>
,这将生成未经检查的类型转换警告。但是,因为你现在obj
是 T
,我认为保留了类型安全。
@SuppressWarnings("unchecked")
public void register(T obj) {
Class<? extends T> klass = (Class<? extends T>) obj.getClass();
this.register(klass);
}
关于java - 如何在运行时获取通配符上限的类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32277554/