Java:getClass()是有界类型
我在使用泛型时注意到了一些东西。在下面的示例中,Java:getClass()是有界类型,java,type-erasure,type-parameter,Java,Type Erasure,Type Parameter,我在使用泛型时注意到了一些东西。在下面的示例中,doStuff1编译,但doStuff2不编译: public <T extends Foo> void doStuff1(T value) { Class<? extends Foo> theClass = value.getClass(); } public <T extends Foo> void doStuff2(T value) { Class<? extends T> t
doStuff1
编译,但doStuff2
不编译:
public <T extends Foo> void doStuff1(T value) {
Class<? extends Foo> theClass = value.getClass();
}
public <T extends Foo> void doStuff2(T value) {
Class<? extends T> theClass = value.getClass();
}
public void doStuff1(T值){
类您不能确定value
实际上是一个T,它也可以是T的子类。getClass()
确实返回value
的“真实”类,但您不能确定它不是,因此它必须阅读Class非常好的问题
java泛型的全部问题是它们在旧的虚拟机中不存在。
Sun决定添加通用支持,而现有虚拟机不支持它们
这可能是一个大问题,因为当它们发布新的Java时,旧的虚拟机将无法运行为最新版本的Java编写的任何代码,并且它们将无法支持旧的虚拟机
因此,他们决定以一种也可以在旧虚拟机中运行的方式实现泛型。
他们决定从字节码中删除它们
所以整个故事都是关于JVM的后台支持
编辑:但这可能与问题无关。请看库奇肯的答案
另外,我的猜测是,在第二种情况下,cast是Class工具提供了一些工具来解决这个限制,并帮助您获得有界类型的类型(so类)
如本说明页第一行所述:
由于类型擦除,您不能同时传递泛型类对象
运行时--您可以强制转换它们并假装它们是泛型的,
但事实并非如此
Guava提供了TypeToken,它使用基于反射的技巧来允许
您需要操作和查询泛型类型,即使在运行时也是如此
其思想是获取(或创建)一个有界类型的,然后您可以请求它的类型
我认为这个答案有点离题,因为它不能直接回答问题(“为什么”部分),但它可以修复不可编译的方法,它可以生成代码来解决问题并给出为什么部分的答案,并且肯定会帮助其他人寻找“Java:-how-getClass()”的有界类型“如果getClass()
返回Class请考虑以下程序:
var a = new ArrayList<String>();
var b = new ArrayList<Integer>();
var aType = a.getClass();
var bType = b.getClass();
if (aType == bType) {
...
}
当然,这意味着您可能需要求助于未经检查的强制转换,以使编译器理解不可转换类型的类对象可能毕竟是相同的…有一种情况需要说明,这种向后兼容性所造成的麻烦比破坏它所带来的麻烦要多,但这是Sun决定的。-)100%同意。这一点可能是我唯一讨厌Java的地方^^^这个问题不是关于类型擦除,而是关于类层次结构。请看我的答案。即使T不是类型参数,而是任何非最终类,那么getClass()还回个Class@kutschkem你说得对。我应该在开始写答案之前考虑一下这些问题,假设我理解了这个问题。^^;@Lake你可能有一部分是对的。毕竟,我没有意识到method2没有编译:-/我认为它可能与擦除和边界相结合有关?弄清楚这一点会让我的头部受伤;我讨厌计算泛型类型边界,即使它还不算太晚。我建议开始并查看搜索规则;这可能是JVM如何在对象的运行时类上发挥其静态魔法的产物。嗯,你的观点呢?class嗯,我的错,我没有仔细阅读,没有看到你的第二种方法od没有编译。我不知何故认为问题在于为什么返回值是Class。你会用什么来代替“…
”?未经检查的强制转换?@5gon12eder——是的。该方法从根本上是不安全的;调用者必须确保它在特定用例中有意义。这是否意味着静态类
String s = "s";
Object o = s;
public <T extends List> void doStuff2(T value) {
Class<? extends T> theClass = (Class<? extends T>) value.getClass();
}
static <X> Class<? extends X> myGetClass(X x){ ... }
var a = new ArrayList<String>();
var b = new ArrayList<Integer>();
var aType = a.getClass();
var bType = b.getClass();
if (aType == bType) {
...
}
@SuppressWarnings("unchecked")
<T> Class<? extends T> getTypedClassOf(T t) {
return (Class) t.getClass();
}