我遇到了泛型问题,而我认为是类型擦除问题,同时试图反映一些通用信息。
我正在使用基于http://www.artima.com/weblogs/viewpost.jsp?thread=208860的课程进行反思,但这不是问题。
下面的代码演示了这个问题:
private <U extends MyClass1> U doSomething(MyClass2<U> p) {
Class<U> classIWant = null;
for (Class<?> c : GenericTypeUtils.getTypeArguments(MyClass2.class, p.getClass())) {
if (MyClass1.class.isAssignableFrom(c)) {
classIWant = c.asSubclass(MyClass1.class);
break;
}
}
}
不幸的是行
classIWant = c.asSubclass(MyClass1.class);
显示以下错误
java: incompatible types
required: java.lang.Class<U>
found: java.lang.Class<capture#4 of ? extends MyClass1>
这真让我感到困惑。 U扩展了MyClass1,因此U是MyClass1。
显然有一些类型的擦除我不明白 - 请有人帮忙。 BTW这是Java 1.7.0_40
由于
康拉德温彻斯特答案 0 :(得分:1)
方法asSubclass()
的实现方式如此
public <U> Class<? extends U> asSubclass(Class<U> clazz) {
if (clazz.isAssignableFrom(this))
return (Class<? extends U>) this;
else
throw new ClassCastException(this.toString());
}
返回类型为Class<? extends U>
。请注意,U
方法中的U
和asSubclass
是完全不相关的类型变量。
因此,方法asSubclass()
返回使用某个未知子类型Class
的类型U
声明的值,其中U
在这种情况下为MyClass1
。
您正尝试将此值分配给Class
类型的变量,其中已知子类型为MyClass1
。编译器不能保证它们匹配,因此不允许编译。
如果您愿意,可以强制转换返回的值,但如果类型不匹配,最终可能会在运行时获得ClassCastException
。
答案 1 :(得分:1)
Java编译器无法保证Class
对象c
与泛型U
匹配。由于类型擦除,编译器需要保证类型安全,并确保从Class
返回的c.asSubclass
与Class<U>
匹配,但不能。{/ p>
The asSubclass
method返回Class<? extends U>
。在Class
班级中,U
表示传递给Class
的{{1}}类型。当你打电话时,那是asSubclass
。但编译器无法保证此返回类型与您自己声明的c
匹配。它们可以是<U extends MyClass1>
的不同子类。
如果你可以保证MyClass1
会返回c.asSubclass
,那么将其投放为Class<U>
:
Class<U>
您将收到“未经检查的演员”警告。这是因为编译器不能保证它确实是classIWant = (Class<U>) c.asSubclass(MyClass1.class);
,但你说的是它。请注意,即使在您返回Class<U>
之后,这可能会导致其他地方难以追踪ClassCastException
。只有在您可以自己保证类型安全的情况下才能这样做。