[英]Java generics compile error involving Class<? extends T>
This program does not compile: 这个程序不编译:
public class xx {
static class Class1<C> {
void method1(C p) {
}
}
static class Class2<T> extends Class1<Class<? extends T>> {
T object;
void method2() {
this.method1(this.object.getClass());
}
}
}
The error is: 错误是:
xx.java:10: method1(java.lang.Class<? extends T>) in xx.Class1<java.lang.Class<? extends T>>
cannot be applied to (java.lang.Class<capture#215 of ? extends java.lang.Object>)
this.method1(this.object.getClass());
Why does this happen? 为什么会这样? Why does the compiler seemingly believe that object.getClass()
returns Class<? extends Object>
为什么编译器似乎相信object.getClass()
返回Class<? extends Object>
Class<? extends Object>
instead of Class<? extends T>
Class<? extends Object>
而不是Class<? extends T>
Class<? extends T>
? Class<? extends T>
?
There is no upper bound set on T
in your code, so ? extends T
您的代码中的T
上没有上限设置,所以? extends T
? extends T
is really tantamount to ? extends Object
? extends T
真的无异于? extends Object
? extends Object
. ? extends Object
。 Just yesterday I played with a similar example and hit this barrier. 就在昨天,我玩了一个类似的例子,并打了这个障碍。 I had 我有
static <T> T newInstance(T o) throws Exception {
final Class<? extends T> c = o.getClass();
return c.newInstance();
}
and it complained with the same error. 它抱怨同样的错误。 Consider this: the return type of Object.getClass()
is Class<?>
and the compiler will want to capture the ?
考虑一下: Object.getClass()
的返回类型是Class<?>
,编译器想要捕获?
into a concrete type. 成为具体类型。 But instead, we would like not to capture the ?
但相反,我们不想捕获?
, but to "capture the upper bound" T
-- and there is no such thing in Java's generics. ,但要“捕获上限” T
- 并且在Java的泛型中没有这样的东西。
Object.getClass()
is defined to return a Class<? extends |T|>
Object.getClass()
被定义为返回一个Class<? extends |T|>
Class<? extends |T|>
, where T
is the statically known type of the receiver (the object getClass()
is called on). Class<? extends |T|>
,其中T
是静态已知类型的接收器(调用对象getClass()
)。 Take special note of the vertical bars, the erasure operator . 特别注意垂直条, 擦除操作符 。 The erasure of a type variable is the erasure of its leftmost bound. 类型变量的擦除是其最左边界的擦除。 In your case that's the implicit bound Object
. 在你的情况下,这是隐式绑定Object
。 So you get back a Class<? extends Object>
所以你得到一个Class<? extends Object>
Class<? extends Object>
, not a Class<? extends T>
Class<? extends Object>
,而不是Class<? extends T>
Class<? extends T>
. Class<? extends T>
。
Why is that? 这是为什么?
Imagine T = List<Integer>
, you could suddenly do the following without unchecked warning : 想象一下T = List<Integer>
,如果没有未经检查的警告 ,您可以突然执行以下操作:
List<String> myStrings = new ArrayList<>();
List<Integer> myInts = new ArrayList<>();
List<Integer> myIntyStrings = myInts.getClass().cast(myStrings);
myIntyStrings.add(-1);
String myString = myStrings.get(0); // BANG!
But thankfully we do get a warning.. ;) 但幸运的是,我们确实收到警告..;)
According to the documentation on getClass(), the returned object has type Class< ? extends |X| >
根据getClass()的文档,返回的对象的类型为Class< ? extends |X| >
Class< ? extends |X| >
Class< ? extends |X| >
, where |X|
Class< ? extends |X| >
,其中|X|
is the erasure of the type of the instance on which the method is called. 是调用该方法的实例类型的擦除。
Therefore calling getClass() on an object of type T
returns Class< ? extends Object >
因此,在类型为T
的对象上调用getClass()会返回Class< ? extends Object >
Class< ? extends Object >
. Class< ? extends Object >
。 We have no bound information about T
in this API. 我们在此API中没有关于T
绑定信息。
Usually APIs which use reflection on generic classes require that the client pass an additional argument of type Class< T >
to the constructor or generic method in question. 通常,在泛型类上使用反射的API要求客户端将类型为Class< T >
的附加参数传递给相关的构造函数或泛型方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.