java.lang.Class泛型和通配符 [英] java.lang.Class generics and wildcards
问题描述
为什么下面的代码不能编译?
interface Iface< T> {}
class Impl< T>实现Iface< T> {}
class TestCase {
static Class< ;?延伸Iface<>> clazz = Impl.class;
}
错误是
< blockquote>
java:不兼容类型: java.lang.Class< Impl>
不能转换为 java.lang.Class< ;?扩展Iface <?>>
但我不明白为什么通配符不会捕获。
这里的子类型关系是:
Class <?扩展Iface>
╱╲
Class <?延伸Iface<>>类<默认地将Impl>
(我在> List< List>转换 code>至列表<列表<>>
' 。)
所以基本上它不会编译,因为它是一个横向转换。
如果可能的话,您可以在那里进行我所描述的投射:
(Class< ;? extends Iface<>)(Class< ;? extends Impl>)Impl.class
如果你不能进行演员表演,那么你可能只需要处理一个原始的
界面Iface< T> {
转换为
void accept(T a);
}
class Impl2实现了Iface< String> {
public void accept(String a){}
}
class TestCase {
static Class <?扩展Iface> clazz = Impl2.class;
public static void main(String [] args)throws Exception {
// throws ClassCastException
clazz.newInstance()。accept(new Object());
$ / code $ / pre
不太可能发生,但这取决于你'重新做我想。
我倾向于认为这是Java类型系统的问题。 b
$ b
可能应该有一个特殊的规则:类型参数
? 扩展 T<>
包含一个类型参数? extends T
,例如<?c $ c> Class <? extends T>Class<? extends T>>< / code>。从定义子类型的现有方式(
T
)是超类型T <?>< / code>),但从类型安全的角度来看它是有意义的。
或者,例如
List.class
应该是Class< List<>>
,而不是类别< List>
。
或者其他聪明的人比我更聪明。 >
上面描述的
ClassCastException
我感兴趣的是它完全是人为的。事实上,通过未经检查的强制转换来阻止它会导致警告。
我猜,Java中的泛型还没有完成。 $ b
Why is is that the following code does not compile?
interface Iface<T> { } class Impl<T> implements Iface<T> { } class TestCase { static Class<? extends Iface<?>> clazz = Impl.class; }
The error is
java: incompatible types:
java.lang.Class<Impl>
cannot be converted tojava.lang.Class<? extends Iface<?>>
but I don't see why the wildcard doesn't capture.
解决方案The subtyping relationship here is:
Class<? extends Iface> ╱ ╲ Class<? extends Iface<?>> Class<Impl>
(Which I explained in my answer to 'Cannot convert from
List<List>
toList<List<?>>
'.)So essentially it doesn't compile because it's a sideways conversion.
If it's possible, you can do the casting I described over there:
(Class<? extends Iface<?>>)(Class<? extends Impl>)Impl.class
If you can't do the cast, then you probably just have to deal with a raw bounded
Class<? extends Iface>
. It's annoying primarily because of the warnings but it opens up the possibility for an error:interface Iface<T> { void accept(T a); } class Impl2 implements Iface<String> { public void accept(String a) { } } class TestCase { static Class<? extends Iface> clazz = Impl2.class; public static void main(String[] args) throws Exception { // throws ClassCastException clazz.newInstance().accept(new Object()); } }
Unlikely to happen, but it depends on what you're doing I suppose.
I tend to think this is a problem with the Java type system.
Possibly there should be a special rule that a type argument
? extends T<?>
contains a type argument? extends T
such that e.g. aClass<? extends T>
converts to aClass<? extends T<?>>
. This doesn't make sense from the perspective of the existing way that subtyping is defined (T
is a supertype ofT<?>
) but it makes sense from the perspective of type safety.Or e.g.
List.class
should be aClass<List<?>>
instead of aClass<List>
.Or some other clever thing people smarter than me can think up.
The interesting thing about the
ClassCastException
I described above is that it's completely artificial. And in fact, preventing it with the unchecked cast causes a warning.Just a sign that generics in Java are not done yet, I guess.
这篇关于java.lang.Class泛型和通配符的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!