2016-09-01 3 views
4

У меня есть список объектов класса, все из которых необходимо расширить класс с помощью универсального типа. Вот мой код:Странная ошибка со списком общих классов

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<?>, он работает во всех случаях, но затем я теряю безопасность типа.

EDIT: Кроме того, если бы я тогда есть этот метод:

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 дает ошибку.

+0

Примечание: 'A ' существует только для простоты, в действительности это расширяет что-то еще. – Squeazer

+2

Я бегу без ошибок, вы имели в виду CLASS_LIST = Arrays.asList (B.class, C.class); вызывает ошибку? – yelliver

+0

Да, это вызывает у меня ошибку. Использование IntelliJ Ultimate 15, компиляция с jdk 1.7.0_79, устанавливается в Java 7. Если я пытаюсь его скомпилировать, он дает ошибку Несовместимые типы. – Squeazer

ответ

-1

Предлагаю вам ознакомиться с исходным кодом JDK.

Метод Arrays.asList возвращает ArrayList - это внутренний класс Array, а не 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 
{ 
    .... 
} 

И внутренний ArrayList класс Массивы в не переопределить метод remove, поэтому он вызывает исключение.

+1

Я думаю, что «я удаляю D.class», OP означает удаление из исходного кода. – WilQu

2

Вы правы, когда вы пишете

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

Компилятор (1,7, 1,8, немного лучше умозаключения типа) выводит тип Class<? extends A<String>> из своих аргументов, что несовместимо с назначением. Вы можете работать, указав нужный тип следующим образом:

Arrays.<Class<? extends A<?>>>asList(B.class, C.class) 
Смежные вопросы