Проблема с генериками
Здесь моя проблема: учитывая эти классы
class A {}
class B extends A {}
Этот код компилируется:
List<Class<? extends A>> list = Arrays.asList(B.class, A.class);
И это не так:
List<Class<? extends A>> anotherList = Arrays.asList(B.class);
Что дает?
ОБНОВЛЕНИЕ: Этот код компилируется в Java 8. По-видимому, из-за "Улучшенного ввода типа".
Ответы
Ответ 1
В первом примере предполагаемым типом вызова Arrays.asList()
является List<Class<? extends A>>
, который, очевидно, присваивается переменной того же типа.
Во втором примере тип правой стороны List<Class<B>>
. Если Class<B>
назначается Class<? extends A>
, List<Class<B>>
не назначается List<Class<? extends A>>
. Он присваивается List<? extends Class<? extends A>>
.
Причиной этого является то же, что и почему List<B>
не присваивается List<A>
. Если бы это было так, это сделало бы следующий (не-типичный) код:
List<Class<B>> bb = new ArrayList<B>();
List<Class<? extends A>> aa = bb;
aa.add(A.class);
Ответ 2
Это скомпилирует:
List<Class<? extends A>> numbers = Arrays.<Class<? extends A>>asList(B.class);
Ответ 3
Arrays.asList(B.class);
генерируется как
List<Class<B>> numbers = Arrays.asList(B.class);
Поскольку он имеет только 1 атрибут типа T
, который соответствует параметризованному типу (в данном случае B.class
).
Ответ 4
Черт возьми, хороший вопрос, и я не знаю ответа, но вот работа вокруг:
List<Class<? extends A>> numbers = new ArrayList<Class<? extends A>>(Arrays.asList(B.class));
Ответ 5
Чтобы добавить, мы можем переписать код ниже
List<Class<? extends A>> asListA = Arrays.asList(B.class, A.class);
List<Class<B>> asListB = Arrays.asList(B.class);
List<Class<? extends A>> numbers = asListA;
List<Class<? extends A>> numbers2 = asListB; // it will fail here
И @Inerdia объяснила детали уже.
Ответ 6
Это проблема ковариации/контравариантности в дженериках. Следующий вопрос SO должен помочь вам понять и решить проблему:
Продемонстрировать ковариацию и контравариантность в Java?
Как будет использоваться контравариантность в Java-дженериках?