Как использовать List <Object> to List <MyClass>
Это не компилируется, любое предложение оценивается.
...
List<Object> list = getList();
return (List<Customer>) list;
Компилятор говорит: не может отбрасывать List<Object>
до List<Customer>
Ответы
Ответ 1
вы всегда можете накладывать любой объект на любой тип, вставляя его сначала в Object. в вашем случае:
(List<Customer>)(Object)list;
вы должны быть уверены, что во время выполнения список не содержит ничего, кроме объектов Customer.
Критики говорят, что такое кастинг указывает на что-то не так с вашим кодом; вы должны уметь настраивать объявления типа, чтобы избежать этого. Но дженерики Java слишком сложны, и это не идеально. Иногда вы просто не знаете, есть ли удовлетворительное решение для компилятора, даже если вы хорошо знаете типы времени выполнения и знаете, что вы пытаетесь сделать, это безопасно. В этом случае просто выполняйте грубое литье по мере необходимости, чтобы вы могли оставить работу для дома.
Ответ 2
Это потому, что, хотя клиент является объектом, список клиентов не является списком объектов. Если бы это было так, вы могли бы поместить любой объект в список Клиентов.
Ответ 3
В зависимости от вашего другого кода лучший ответ может отличаться.
Попробуйте:
List<? extends Object> list = getList();
return (List<Customer>) list;
или
List list = getList();
return (List<Customer>) list;
Но имейте в виду, что не рекомендуется делать такие непроверенные броски.
Ответ 4
Вы можете использовать двойной бросок.
return (List<Customer>) (List) getList();
Ответ 5
С Java 8 Streams:
Иногда можно просто использовать метод грубой силы:
List<MyClass> mythings = (List<MyClass>) (Object) objects
Но здесь есть более универсальное решение:
List<Object> objects = Arrays.asList("String1", "String2");
List<String> strings = objects.stream()
.map(element->(String) element)
.collect(Collectors.toList());
Существует множество преимуществ, но одно из них заключается в том, что вы можете составить свой список более элегантно, если не уверены, что в нем содержится:
objects.stream()
.filter(element->element instanceof String)
.map(element->(String)element)
.collect(Collectors.toList());
Ответ 6
Обратите внимание, что я не программист на Java, но в .NET и С# эта функция называется контравариацией или ковариацией. Я еще не углубился в эти вещи, поскольку они новы в .NET 4.0, которые я не использую, поскольку это только бета-версия, поэтому я не знаю, какой из этих двух терминов описывает вашу проблему, но позвольте мне описать техническая проблема с этим.
Предположим, вам разрешили бросить. Заметьте, я говорю "cast", так как вы сказали, но есть две операции, которые могут быть возможны, кастинг и преобразование.
Преобразование означало бы, что вы получаете новый объект списка, но вы говорите о кастинге, что означает, что вы хотите временно относиться к одному объекту как к другому типу.
Здесь проблема с этим.
Что произойдет, если будет разрешено следующее (обратите внимание, что я предполагаю, что до трансляции список объектов фактически содержит объекты Customer, иначе кастинг не будет работать даже в этой гипотетической версии java):
List<Object> list = getList();
List<Customer> customers = (List<Customer>)list;
list.Insert(0, new someOtherObjectNotACustomer());
Customer c = customers[0];
В этом случае это попытается обработать объект, который не является клиентом, в качестве клиента, и вы получите ошибку времени выполнения в одной точке, либо в форме внутри списка, либо из назначения.
Однако, как правило, универсальные данные предоставляют вам типы данных типа типа, такие как коллекции, и поскольку они любят бросать слово "гарантировано", этот тип приведения, с последующими проблемами, не допускается.
В .NET 4.0 (я знаю, ваш вопрос касался java), это будет разрешено в некоторых очень конкретных случаях, когда компилятор может гарантировать, что операции, которые вы делаете, безопасны, но в общем смысле этот тип бросок не будет разрешен. То же самое можно сказать и о java, хотя я не уверен в каких-либо планах введения ковариации и контравариантности в язык Java.
Надеюсь, кто-то с лучшим знанием java, чем я, может рассказать вам о специфике будущего java или реализации.
Ответ 7
Другим подходом будет использование потока java 8.
List<Customer> customer = myObjects.stream()
.filter(Customer.class::isInstance)
.map(Customer.class::cast)
.collect(toList());
Ответ 8
Вы должны просто перебирать список и бросать все объекты по одному
Ответ 9
Вы можете сделать что-то вроде этого
List<Customer> cusList = new ArrayList<Customer>();
for(Object o: list){
cusList.add((Customer)o);
}
return cusList;
Или способ Java 8
list.stream().forEach(x->cusList.add((Customer)x))
return cuslist;
Ответ 10
Вы не можете, потому что List<Object>
и List<Customer>
не находятся в одном дереве наследования.
Вы можете добавить новый конструктор в класс List<Customer>
, который принимает List<Object>
, а затем перебирает список, отбрасывая каждый Object
до Customer
и добавляя его в свою коллекцию. Имейте в виду, что может произойти недопустимое исключение броска, если вызывающий List<Object>
содержит то, что не является Customer
.
Точка общих списков состоит в том, чтобы ограничить их определенными типами. Вы пытаетесь взять список, который может иметь что-нибудь в нем (Заказы, Продукты и т.д.) И втиснуть его в список, который может принимать только клиенты.
Ответ 11
Лучше всего создать новый List<Customer>
, выполнить итерацию через List<Object>
, добавить каждый элемент в новый список и вернуть его.
Ответ 12
Как указывали другие, вы не можете их применять, так как List<Object>
не является List<Customer>
. Что вы можете сделать, это определить представление в списке, который выполняет проверку типа на месте. Используя Коллекции Google, которые будут:
return Lists.transform(list, new Function<Object, Customer>() {
public Customer apply(Object from) {
if (from instanceof Customer) {
return (Customer)from;
}
return null; // or throw an exception, or do something else that makes sense.
}
});
Ответ 13
В зависимости от того, что вы хотите сделать с этим списком, вам может даже не понадобиться отбрасывать его на List<Customer>
. Если вы хотите добавить в список объекты Customer
, вы можете объявить их следующим образом:
...
List<Object> list = getList();
return (List<? super Customer>) list;
Это законно (ну, не только юридически, но правильно - список имеет "некоторый супертип для Клиента" ), и если вы собираетесь передать его в метод, который будет просто добавлять объекты в список то для этого достаточно общих общих оценок.
С другой стороны, если вы хотите извлекать объекты из списка и набирать их строго как клиенты - тогда вам не повезло, и это правильно. Поскольку список является List<Object>
, нет никаких гарантий, что содержимое является клиентом, поэтому вам придется предоставить свое собственное кастинг при поиске. (Или действительно, абсолютно, вдвойне уверен, что список будет содержать только Customers
и использовать двойное нажатие из одного из других ответов, но поймите, что вы полностью обходите безопасность типа компиляции, которую вы получаете от дженерики в этом случае).
В целом, всегда полезно рассматривать максимально широкие общие границы, которые были бы приемлемы при написании метода, вдвойне, если он будет использоваться в качестве библиотечного метода. Если вы только собираетесь читать из списка, используйте List<? extends T>
вместо List<T>
, например - это дает вашим абонентам гораздо больше возможностей в аргументах, которые они могут передать, и означает, что они с меньшей вероятностью столкнутся с возможными проблемами подобный тому, который у вас здесь.
Ответ 14
Вы можете создать новый список и добавить к нему элементы:
Например:
List<A> a = getListOfA();
List<Object> newList = new ArrayList<>();
newList.addAll(a);
Ответ 15
Аналогично Божо выше. Вы можете сделать некоторое обходное решение здесь (хотя мне это не нравится) с помощью этого метода:
public <T> List<T> convert(List list, T t){
return list;
}
Да. Он перечислит ваш список в ваш требуемый общий тип.
В данном случае выше вы можете сделать такой код:
List<Object> list = getList();
return convert(list, new Customer());
Ответ 16
Не самый эффективный подход, но:
List<Customer> customers = new ArrayList<Customers>(getList());