泛型类列表的奇怪错误

时间:2016-09-01 08:24:30

标签: java generics

我有一个Class对象列表,所有这些对象都需要扩展一个泛型类。这是我的代码:

private final List<Class<? extends A<?>>> CLASS_LIST =
        Arrays.asList(B.class, C.class, D.class);

// Base class
private abstract class A<T extends Object> {}

// Some class that extends A
private class B extends A<String> {}

// Some other class that extends A
private class C extends A<String> {}

// A class that extends A, but with a different type than the first two
private class D extends A<OtherClass> {}

private static class OtherClass {}

这样可以正常工作,但是如果从列表中删除D.class,我会收到错误消息:

Incompatible types, Required A<?>, found A<String>

为什么会这样?我假设Java推断出类型......但为什么呢?它有办法吗?我发现如果我使用List<?>它在所有情况下都有效,但后来我失去了类型安全性。

修改 此外,如果我有这个方法:

private void Check(){
    A a = new B();

    if(CLASS_LIST.contains(a.getClass())){
        // Do something
    }
}

它向我发出了List.contains(...)可疑电话的警告。但是,如果我使用List<?>,警告会消失......为什么会这样?

EDIT2: Java 1.8.0_51-b16编译,但Java 1.7.0_79给出了错误。

2 个答案:

答案 0 :(得分:2)

你写的时候是对的

Arrays.asList(B.class, C.class)

编译器(1.7,1.8在类型推断方面稍微好一点)从其参数中推断出Class<? extends A<String>>的类型,这与赋值不兼容。您可以通过指定所需的类型来解决此问题:

Arrays.<Class<? extends A<?>>>asList(B.class, C.class)

答案 1 :(得分:-1)

我建议你看看JDK源代码。

方法Arrays.asList返回一个ArrayList是Arrays的内部类,而不是java.util.ArrayList。

public static <T> List<T> asList(T... a) {
    return new ArrayList<>(a);
}

/**
* @serial include
*/
private static class ArrayList<E> extends AbstractList<E>
    implements RandomAccess, java.io.Serializable
{
    ....
}

并且Arrays的内部类ArrayList不会覆盖remove方法,因此会引发异常。