java.lang.Class泛型和通配符 [英] java.lang.Class generics and wildcards

查看:75
本文介绍了java.lang.Class泛型和通配符的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么下面的代码不能编译?

  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 

如果你不能进行演员表演,那么你可能只需要处理一个原始的 Class< ;?&NBSP;延伸&NBSP; IFACE> 。它很烦人,主要是因为警告,但它可能导致错误:

 界面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 to java.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> to List<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. a Class<? extends T> converts to a Class<? extends T<?>>. This doesn't make sense from the perspective of the existing way that subtyping is defined (T is a supertype of T<?>) but it makes sense from the perspective of type safety.

  • Or e.g. List.class should be a Class<List<?>> instead of a Class<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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆