使用边界编译泛型时出错

时间:2016-07-27 16:09:40

标签: java generics

我对泛型有疑问。

我在一个类中有这个片段(我们称之为案例1):

static {
    final List<Class<? extends A>> typeList = Arrays.asList(
        C.class,
        D.class
    );
}

public interface A {…}

public class C extends B {…}

public class D extends B {…}

public abstract class B implements A {…}

Android Studio抱怨并且无法在上面的final List…行编译:

  

不兼容的类型
  必需清单&lt;的类&LT ;?扩展A&gt; &gt;
  找到列表&lt;的类&LT ;?扩展B&gt; &gt;

但是,之前我有这个代码(让我们称之为案例2):

static {
    final List<Class<? extends A>> typeList = Arrays.asList(
        C.class,
        D.class
    );
}

public interface A {…}

public class C implements A {…}

public class D implements A {…}

并编译。

所以,我试过,只是为了缩小问题范围,将案例1改为:

static {
    final List<Class<? extends A>> typeList = Arrays.asList(
        B.class
    );
}

请注意B实现A,就像案例二中的C和D.但编译器仍抱怨。

我没有理解这个问题的想法,我阅读了Java Language Specification类型和值章节,但仍然没有。

我在StackOverflow上搜索过,但我没有找到类似的问题。

任何指针? (PS:在某人做之前强制XKCD

1 个答案:

答案 0 :(得分:6)

问题是类型推断的问题。在Java 8之前,编译器在推断使用typeList类型来确定Arrays.asList的实例化时不够聪明,因此这是孤立的。

尝试这个明确的提示:

final List<Class<? extends A>> typeList = Arrays.<Class<? extends A>>asList(
    B.class
);

更详细地说,编译器只是孤立地看到了这一点:

Arrays.asList(
    C.class,
    D.class
);

没有看到它分配给它的内容。它选择Class<? extends B>而不是Class<? extends A>,因为这是所有参数共有的最具体的超类型。