Java: приведение из списка <B>к списку <A>, когда B реализует A? - PullRequest
4 голосов
/ 26 сентября 2010

У меня определен следующий класс и интерфейс:

public interface A {
}

public class B implements A {
}

У меня есть List из B объектов, которые мне нужно преобразовать в List из A объектов:

List<B> listB = new List<B>();
listB.add(new B());  // dummy data
listB.add(new B());  // dummy data
listB.add(new B()); // dummy data

List<A> listA = (List<A>) listB;

Последняя строка выше приводит к ошибке компиляции "Невозможно привести из списка в список ". Вместо этого я попытался обойти это с помощью следующего:

List<A> listA = Arrays.asList((A[]) listB.toArray());

К сожалению, это бросает ClassCastException. Кто-нибудь знает, как я могу решить эту проблему?

Ответы [ 7 ]

14 голосов
/ 26 сентября 2010

Вы не можете разыграть это так. Создайте новый:

List<A> listA = new ArrayList<A>(listB);

Конструктор занимает Collection<? extends A>. В любом случае он будет указывать на одни и те же ссылки.

9 голосов
/ 13 августа 2012

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

Вместо того, чтобы спрашивать, как использовать небезопасные приведения для обхода ошибки, полезно сначала понять почему есть ошибка; почему то, что вы просите сделать, небезопасно (потому что вы можете добавить A в список, используя listA, а затем вывести его из списка как B, используя listB).

Затем вы должны объяснить , почему вы считаете, что ваш вариант использования не соответствует небезопасному сценарию.Потому что ответ на это даст подсказку о том, как изменить ваш код, чтобы он корректно работал с универсальными шаблонами.

  • Если вы скажете, что это небезопасно, потому что вы никогда не добавляете ничего, используя listA,тогда вы должны изменить тип listA на List<? extends A>.Таким образом, вы можете назначить listB ему напрямую без каких-либо преобразований, и вы не сможете ничего добавить к нему, используя listA (кроме null).
  • Если вы скажете, что этоне является небезопасным, потому что вы никогда ничего не получите, используя listB, тогда почему бы не изменить тип listB на List<A> в первую очередь?
6 голосов
/ 26 сентября 2010

Вы можете просто использовать стирание типа, если знаете, что операция безопасна. Это выдает предупреждение, которое вы можете отключить с помощью @ SuppressWarnings

List<A> listA = (List) listB;

Причина, по которой компилятор испытывает трудности с простым приведением, состоит в том, что теперь вы можете добавить класс C, который также реализует A. За исключением того, что ваш первоначальный список был изменен и теперь содержит C, даже если вы указали, что это не должно быть.

3 голосов
/ 26 сентября 2010
List<A> listA = (List<A>)(List<?>) listB;

не рекомендуется.

1 голос
/ 26 сентября 2010

Я уверен, что вам нужно составить весь список List (странный разбор там) и при добавлении новых объектов B приводите их к (A)

listA.add( (A) new B());  // dummy data
0 голосов
/ 11 июня 2018

Мы можем достичь этого, используя Generics и Wildcards.Возможно, вы не сможете создать List<A>, но создадите что-то вроде List<? extends A>, которое будет вызывать все методы интерфейса, что, как мне кажется, достаточно для большинства.

Создание новой коллекции стоит дорого и не рекомендуется.Поскольку ссылки на одни и те же объекты будут переданы в новую коллекцию, дополнительный этап создания списка - это просто накладные расходы.

List<B> bList = new ArrayList<B>();

List<? extends A> aList = bList;
0 голосов
/ 11 апреля 2018

Это просто вопрос деклараций. Не объявляйте listB как список, но как список или список.

List<A> listB = new List<B>();
listB.add(new B());  // dummy data
listB.add(new B());  // dummy data
listB.add(new B()); // dummy data

List<A> listA = listB;

Так просто. Если вы хотите, чтобы listB был List (исключая добавление любого не-B элемента), вы будете вынуждены использовать:

List<A> listA = new ArrayList<A>(listB);

Но, как они уже указывали, если вас заставляют это делать, это не очень хороший знак.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...