Java中的通用方法参数的getClass()
以下Java方法无法编译:
void foo(T t) { Class klass = t.getClass(); }
收到的错误是:类型不匹配:无法转换为Class
Class
为Class
Class
有人可以解释为什么Class
Class
无效,但Class
Class
?
Javadoc说:
实际的结果类型是
Class
Class
where | X | 是擦除调用getClass的表达式的静态类型。 例如,此代码片段中不需要强制转换:
Number n = 0; Class c = n.getClass();
因为T
类’类型不会从T
延伸。 相反,它从Number
扩展,正如您在
。 就那么简单。
一个更好的问题是:
以下为什么不编译?
void foo(T t) { Class class1 = t.getClass(); }
答案是Object#getClass()
返回带有无界通配符的Class>
?
因为对象本身并不直接了解其在任意方法中所期望的generics类型。
这有点傻。 对于大多数用例来说,如果x.getClass()
返回Class extends X>
Class extends X>
,而不是擦除的Class extends |X|>
Class extends |X|>
。
擦除是导致信息丢失的原因,使您的代码显然是安全的,无法编译。 t.getClass()
返回Class extends |T|>
Class extends |T|>
和|T| = Number
|T| = Number
,所以返回Class extends Number>
Class extends Number>
。
擦除(由语言规范强制要求)是为了保持理论上的正确性。 例如
List x = ...; Class c1 = x.getClass(); // ok Class> c2 = x.getClass(); // error
虽然c2看起来很合理,但在Java中, List
实际上没有这样的类。 List
只有一个类。 所以允许c2理论上是不正确的。
这种forms在现实世界的用法中产生了很多问题,程序员可以推断出Class extends X>
Class extends X>
对于他们的目的是安全的,但必须处理已删除的版本。
您可以简单地定义自己的getClass
,返回未擦除的类型
static public Class extends X> getFullClass(X x) return (Class extends X>)(Class) x.getClass() ; void foo(T t) { Class extends T> klass = getFullClass(t); }