首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >java.lang.Class泛型和通配符

java.lang.Class泛型和通配符
EN

Stack Overflow用户
提问于 2015-05-07 01:09:18
回答 2查看 932关注 0票数 6

为什么下面的代码没有编译?

代码语言:javascript
复制
interface Iface<T> { }

class Impl<T> implements Iface<T> { }

class TestCase {
    static Class<? extends Iface<?>> clazz = Impl.class;
}

错误是

java.lang.Class<Impl>:不兼容类型:无法将java.lang.Class<? extends Iface<?>>转换为java.lang.Class<? extends Iface<?>>

但我不明白为什么通配符没有捕捉到。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-05-07 04:32:58

这里的子类型关系是:

代码语言:javascript
复制
          Class<? extends Iface>
           ╱                  ╲
Class<? extends Iface<?>>   Class<Impl>

(我在对的答复中解释了这一点。)

所以本质上它不编译,因为它是一个横向的转换。

如果可能的话,你可以做我在那里描述的演员:

代码语言:javascript
复制
(Class<? extends Iface<?>>)(Class<? extends Impl>)Impl.class

如果您不能进行强制转换,那么您可能只需要处理一个原始的有界Class<? extends Iface>。这很烦人,主要是因为警告,但它可能会出现错误:

代码语言:javascript
复制
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());
    }
}

不太可能发生,但这取决于你在做什么。

我倾向于认为这是Java类型系统的一个问题。

  • 可能应该有一个特殊的规则,即类型参数? extends T<?>包含类型参数? extends T,例如,Class<? extends T>将转换为Class<? extends T<?>>。从定义子类型的现有方式(TT<?>的超级类型)的角度来看,这是没有意义的,但从类型安全性的角度来看,这是有意义的。
  • 或者,List.class应该是Class<List<?>>而不是Class<List>
  • 或者其他比我聪明的人能想到的聪明的东西。

我上面描述的ClassCastException的有趣之处在于,它完全是人为的。事实上,使用未检查的强制转换来阻止它会引起警告。

我想,这只是一个迹象,表明Java中的泛型还没有完成。

票数 3
EN

Stack Overflow用户

发布于 2015-05-07 01:24:04

因为类型擦除,当你说Impl.class时,你会得到一个Class<Impl>。也就是说,你可以说

代码语言:javascript
复制
Class<Impl> clazz = Impl.class;

泛型是编译时类型安全的特性.

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30090242

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档