Вопрос-ответ

How do you cast a List of supertypes to a List of subtypes?

Как преобразовать список супертипов в список подтипов?

Например, допустим, у вас есть два класса:

public class TestA {}
public class TestB extends TestA{}

У меня есть метод , который возвращает List<TestA> и я хотел бы преобразовать все объекты в этом списке в TestB так, чтобы в итоге получилось List<TestB>.

Переведено автоматически
Ответ 1

Простое преобразование в List<TestB> почти работает; но это не работает, потому что вы не можете преобразовать общий тип одного параметра в другой. Однако вы можете использовать промежуточный подстановочный тип, и это будет разрешено (поскольку вы можете выполнять приведение к подстановочным типам и из них, просто с непроверенным предупреждением):

List<TestB> variable = (List<TestB>)(List<?>) collectionOfListA;
Ответ 2

Приведение обобщений невозможно, но если вы определяете список другим способом, в нем можно сохранить TestB:

List<? extends TestA> myList = new ArrayList<TestA>();

Вам все еще нужно выполнять проверку типов, когда вы используете объекты в списке.

Ответ 3

С Java 8 вы действительно можете

List<TestB> variable = collectionOfListA
.stream()
.map(e -> (TestB) e)
.collect(Collectors.toList());
Ответ 4

Вы действительно не можете*:

Пример взят из этого руководства по Java

Предположим, что существует два типа A и B такие, что B extends A. Тогда следующий код правильный:

    B b = new B();
A a = b;

Предыдущий код допустим, потому что B является подклассом A.
Теперь, что происходит с List<A> и List<B>?

Оказывается, что List<B> не является подклассом List<A>, поэтому мы не можем написать

    List<B> b = new ArrayList<>();
List<A> a = b; // error, List<B> is not of type List<A>

Более того, мы не можем даже написать

    List<B> b = new ArrayList<>();
List<A> a = (List<A>)b; // error, List<B> is not of type List<A>

*: Чтобы сделать приведение возможным, нам нужен общий родительский элемент для обоих, например, для List<A> и List<B>: List<?>. Следующее является допустимым:

    List<B> b = new ArrayList<>();
List<?> t = (List<B>)b;
List<A> a = (List<A>)t;

Однако вы получите предупреждение. Вы можете подавить его, добавив @SuppressWarnings("unchecked") в свой метод.

java list generics collections