Java:有界类型的getClass()

当我在使用仿制药时,我发现了一些东西。 在下面的示例中, doStuff1编译但doStuff2不编译:

 public  void doStuff1(T value) { Class theClass = value.getClass(); } public  void doStuff2(T value) { Class theClass = value.getClass(); } 

所以,我查找了Object.getClass()的文档,发现了这个:

实际的结果类型是Class <? extends | X |> where | X | 是擦除调用getClass的表达式的静态类型。

这让我有点好奇。 为什么getClass()这种方式设计? 如果适用的话,我可以理解将类型转换为它们的原始类,但是我没有明显的理由说明为什么它们必须使它同时杀掉T 有没有一个特定的原因,它也可以摆脱它,或者它只是一个普遍的“让我们摆脱一切因为它更容易;谁会永远需要它”的方法?

如果getClass()返回Class Class ,没有什么不好的事情可以发生; 实际上它会帮助很多用例。

唯一的问题是,它在理论上是不正确的。 如果一个对象是一个ArrayList ,它的class不能是Class> – 没有这样的类,只有一个Class

这实际上与擦除无关。 如果有一天Java获得完整的reified类型, getClass()应该仍然返回Class Class ; 但是应该有一个新方法,比如getType()可以返回更详细的Type Type 。 (但是, getType可能与许多现有类与自己的getType方法冲突)

对于时间,因为Class Class在很多情况下可能很有用,我们可以设计自己的方法来做到这一点

 static  Class myGetClass(X x){ ... } 

但是可以理解他们不会把这种黑客放在标准的lib中。

你不能确定这个value实际上是一个T,它也可能是T的子类getClass()确实返回了“真正的”类value ,但你不能确定它是T,因此它必须读取Class Class ! 这与T是类型参数的事实无关。

[编辑]好吧不太好,我没有意识到method2没有编译。 我认为这是编译器问题。 我明白了

 Type mismatch: cannot convert from Class to Class 

我认为编译器只会意识到T对象是Foo。 编译器应该知道getClass()返回一些Class Class但似乎只知道它返回一些Class Class 。 这是否意味着Foo是erasure of the static type T的erasure of the static type

非常好的问题。

javagenerics的整个问题是它们在旧虚拟机中不存在。 Sun决定添加通用支持,而现有虚拟机不支持它们。

这可能是一个大问题,因为当它们发布新的Java时,旧的虚拟机将无法运行为最新版本的Java编写的任何代码,并且它们将无法支持旧版本的旧虚拟机。

因此,他们决定以可以在旧虚拟机中运行的方式实现generics。 他们决定从BYTECODE中删除他们。

所以整个故事都是关于jvms的支持。

编辑:但这可能与这个问题无关。 看kutschkem的回答!

另外,我的猜测是,在第二种情况下,演员是Class ClassClass Class 。 只有当List直接扩展T(因为它是隐式转换)时才能进行此转换。 但另一方面,T扩展了List。

我认为它与说法相同:

 String s = "s"; Object o = s; 

在上面的例子中,强制转换是可能的,因为String扩展了Object。 对于反向,您需要一个显式的强制转换。

如果您向程序添加显式强制转换,它将编译:

 public  void doStuff2(T value) { Class theClass = (Class) value.getClass(); } 

番石榴reflection工具提供了一些工具来解决这个限制,并帮助您获得有界类型的类型(所以类)。

正如本说明页面第一行所述:

由于类型擦除,您无法在运行时传递generics类对象 – 您可能能够转换它们并假装它们是通用的,但它们实际上并非如此。

Guava提供了TypeToken,它使用基于reflection的技巧来允许您操作和查询generics类型,即使在运行时也是如此。

想法是获取(或创建)有界类型的TypeToken ,然后您可以询问其类型。

我认为这个答案有点偏离主题,因为它没有直接回答问题(’为什么’部分),但它可以修复不可编译的方法,它可以导致代码能够解决问题并给出你找到原因的答案部分,肯定会帮助其他人寻找’Java: – 如何-getClass()的有界类型“