Cómo convertir Lista en List

Esto no comstack, cualquier sugerencia apreciada.

... List list = getList(); return (List) list; 

El comstackdor dice: no se puede convertir la List a la List

siempre puedes lanzar cualquier objeto a cualquier tipo mediante su conversión ascendente a Objeto primero. en tu caso:

 (List)(Object)list; 

debe estar seguro de que, en tiempo de ejecución, la lista no contiene más que objetos del Cliente.

Los críticos dicen que ese casting indica algo mal con tu código; deberías poder modificar tus declaraciones de tipo para evitarlo. Pero los generics de Java son demasiado complicados, y no son perfectos. A veces simplemente no se sabe si hay una solución bonita para satisfacer al comstackdor, a pesar de que usted conoce muy bien los tipos de tiempo de ejecución y sabe que lo que está tratando de hacer es seguro. En ese caso, solo haga la fundición de crudo según sea necesario, para que pueda dejar el trabajo para el hogar.

Esto se debe a que, aunque un Cliente es un Objeto, una Lista de Clientes no es una Lista de Objetos. Si fuera así, podría colocar cualquier objeto en una lista de Clientes.

Dependiendo de tu otro código, la mejor respuesta puede variar. Tratar:

 List< ? extends Object> list = getList(); return (List) list; 

o

 List list = getList(); return (List) list; 

Pero tenga en cuenta que no se recomienda hacer tales lanzamientos sin marcar.

Puedes usar un doble elenco.

 return (List) (List) getList(); 

Con Java 8 Streams :

A veces, la fundición de fuerza bruta está bien:

 List mythings = (List) (Object) objects 

Pero aquí hay una solución más versátil:

 List objects = Arrays.asList("String1", "String2"); List strings = list.stream() .map(element->(String) element) .collect(Collectors.toList()); 

Hay un montón de beneficios, pero uno es que puedes lanzar tu lista de forma más elegante si no puedes estar seguro de lo que contiene:

 list.stream() .filter(element->element instanceof String) .map(element->(String)element) .collect(Collectors.toList()); 

Tenga en cuenta que no soy un progtwigdor de Java, pero en .NET y C #, esta característica se llama contravarianza o covarianza. Todavía no me he adentrado en esas cosas, ya que son nuevas en .NET 4.0, que no estoy usando porque es solo beta, así que no sé cuál de los dos términos describe tu problema, pero déjame describir el problema técnico con esto.

Supongamos que se te permitió lanzar. Tenga en cuenta, digo el reparto , ya que eso es lo que dijiste, pero hay dos operaciones que podrían ser posibles, fundición y conversión .

Conversión significaría que obtienes un nuevo objeto de lista, pero dices conversión, lo que significa que quieres tratar temporalmente un objeto como otro tipo.

Aquí está el problema con eso.

Qué pasaría si se permitiera lo siguiente (nota, supongo que antes del elenco, la lista de objetos en realidad solo contiene objetos de Cliente, de lo contrario el molde no funcionaría incluso en esta versión hipotética de Java):

 List list = getList(); List customers = (List)list; list.Insert(0, new someOtherObjectNotACustomer()); Customer c = customers[0]; 

En este caso, esto intentaría tratar a un objeto, que no es un cliente, como cliente, y obtendría un error de tiempo de ejecución en un punto, ya sea dentro de la lista o desde la tarea.

Sin embargo, se supone que los generics le brindan tipos de datos seguros para el tipo, como colecciones, y dado que les gusta arrojar la palabra ‘garantizado’, este tipo de molde, con los problemas que siguen, no está permitido.

En .NET 4.0 (lo sé, tu pregunta fue sobre Java), esto se permitirá en algunos casos muy específicos , donde el comstackdor puede garantizar que las operaciones que realizas son seguras, pero en el sentido general, este tipo de elenco no ser permitido. Lo mismo vale para Java, aunque no estoy seguro de ningún plan para introducir co y contravariancia en el lenguaje Java.

Con suerte, alguien con mejor conocimiento de Java que yo puede decirle los detalles para el futuro de Java o la implementación.

Debería iterar sobre la lista y lanzar todos los objetos uno a uno

No se puede porque List y List no están en el mismo árbol de herencia.

Puede agregar un nuevo constructor a su clase List que toma una List y luego iterar a través de la lista que envía cada Object a un Customer y agregarlo a su colección. Tenga en cuenta que una excepción de conversión no válida puede ocurrir si la List la persona que llama List contiene algo que no es un Customer .

El objective de las listas genéricas es restringirlas a ciertos tipos. Está intentando tomar una lista que puede incluir cualquier cosa (Pedidos, Productos, etc.) y exprimirla en una lista que solo puede llevar a los Clientes.

Su mejor opción es crear una nueva List , repetir a través de la List , agregar cada elemento a la nueva lista y devolverlo.

Como han señalado otros, no puede lanzarlos salvablemente, ya que una List no es una List . Lo que podría hacer es definir una vista en la lista que haga una verificación de tipo in situ. Usando colecciones de Google que serían:

 return Lists.transform(list, new Function() { 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. } }); 

Dependiendo de lo que quiera hacer con la lista, es posible que ni siquiera necesite enviarla a una List . Si solo desea agregar objetos de Customer a la lista, puede declararlo de la siguiente manera:

 ... List list = getList(); return (List< ? super Customer>) list; 

Esto es legal (bueno, no solo legal, sino correcto , la lista es de “algún supertipo para el Cliente”), y si va a pasarlo a un método que simplemente agregará objetos a la lista, entonces lo anterior los límites generics son suficientes para esto.

Por otro lado, si desea recuperar objetos de la lista y tenerlos fuertemente tipificados como Clientes, entonces no tiene suerte, y con razón. Debido a que la lista es una List no hay garantía de que los contenidos sean clientes, por lo que tendrá que proporcionar su propio molde en la recuperación. (O estar realmente, absolutamente, doblemente seguro de que la lista solo contendrá Customers y usará un doble cast de una de las otras respuestas, pero se dará cuenta de que está eludiendo por completo el tipo de seguridad en tiempo de comstackción que obtiene de los generics en este caso).

En términos generales, siempre es bueno considerar los límites generics más amplios posibles que serían aceptables al escribir un método, doblemente si se va a utilizar como un método de biblioteca. Si solo va a leer de una lista, use List< ? extends T> List< ? extends T> lugar de List , por ejemplo, esto les brinda a los llamadores mucho más scope en los argumentos que pueden transmitir y significa que es menos probable que se topen con problemas evitables similares a los que tiene aquí.

Puedes hacer algo como esto

 List cusList = new ArrayList(); for(Object o: list){ cusList.add((Customer)o); } return cusList; 

O la forma de Java 8

 list.stream().forEach(x->cusList.add((Customer)x)) return cuslist; 

Similar con Bozho arriba. Puede hacer alguna solución aquí (aunque a mí mismo no me gusta) a través de este método:

 public  List convert(List list, T t){ return list; } 

Sí. Emitirá su lista en su tipo genérico exigido.

En el caso dado anterior, puede hacer un código como este:

  List list = getList(); return convert(list, new Customer()); 

Otro enfoque sería usar una secuencia java 8.

  List customer = myObjects.stream() .filter(Customer.class::isInstance) .map(Customer.class::cast) .collect(toList()); 

Puede crear una nueva lista y agregarle los elementos:

Por ejemplo:

 List a = getListOfA(); List newList = new ArrayList<>(); newList.addAll(a);