Как использовать 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());