2009-09-30 20 views
17

Tengo una lista que garantiza que solo contiene un objeto de tipo. Esto es creado por algún código subyacente en una biblioteca que no puedo actualizar. Quiero crear una lista <ObjectType> basada en el objeto List entrante para que mi código de llamada esté en la lista <ObjectType>.Conversión de tipo de lista no genérico a tipo de lista genérica en Java 1.5

¿Cuál es la mejor forma de convertir la Lista (o cualquier otra colección de objetos) en una lista < Tipo de objeto >.

Respuesta

13

Cuando inter-operar con código heredado que no especifica los parámetros de tipo para los tipos genéricos, utilice un comodín. Por ejemplo, supongamos que usted está llamando a un método en una biblioteca antigua que simplemente devuelve una prima Collection:

Collection getItems(); 

En su código, asignar el resultado a una variable declarada con un comodín:

Collection<?> items = widget.getItems(); 

Este De esta manera, conservas la seguridad del tipo para que no recibas ninguna advertencia.

El código heredado podría especificar (lo más probable es que en un comentario) cuáles deberían ser los parámetros genéricos. Por ejemplo:

/** 
* @return the items, as a Collection of {@link Item} instances. 
*/ 
Collection getItems(); 

En este caso, tiene una opción. Usted puede arrojar el resultado a Collection<Item>, pero si lo hace, está confiando 100% en la biblioteca de terceros, y descartando la seguridad de los tipos genéricos de Java: que cualquier ClassCastException generado en tiempo de ejecución ocurrirá en un explícito emitir.

¿Qué sucede si no confía plenamente en la biblioteca de terceros, pero todavía necesita producir un Collection<Item>? Luego, cree una nueva colección y agregue los contenidos después de enviarlos al tipo esperado. De esta forma, si hay un error en la biblioteca, lo descubres enseguida, en lugar de tener un código muy lejos y mucho más tarde explotar misteriosamente con un ClassCastException.

Por ejemplo:

Collection<?> tmp = widget.getItems(); 
Collection<Item> items = new ArrayList<Item>(tmp.size()); 
for (Object o : tmp) 
    items.add((Item) o); /* Any type error will be discovered here! */ 

Para un caso en el que el parámetro de tipo no se conoce en tiempo de compilación, puede utilizar la type-checked collection factories de la clase Collections.

+0

El problema es que eso no te gana nada más que silenciar las advertencias de "tipo sin formato". ¡Convertir a los genéricos implicaría hacer uso de sus beneficios! –

+1

¿Cuál es el beneficio de los genéricos? ¡No es para hacer que tu código se vea bonito y requiera menos tipeo! Es esto: * Se garantiza que su código será seguro si se compila sin advertencias. * Eso es todo. Cuando ignoras o suprimes las advertencias, es mejor que no uses genéricos en absoluto, porque todo lo que estás haciendo es crear situaciones en las que código sin un operador de conversión misteriosamente provoca 'ClassCastException'. – erickson

11

Usted puede simplemente echar la lista:

List raw = new ArrayList(); 
    List<String> generic = (List<String>) raw; 
+2

Si la lista está garantizada para contener un tipo de artículo, esta es una buena respuesta. –

+1

Eso es un gran "si". Depende mucho del contexto. – erickson

+0

Puedo garantizar que la lista contenga un tipo de artículo. Este fue el código escrito en Java 1.4 pre-genéricos. –

1

La forma mejor y más segura es utilizar el método java.util.Collections 'checkedList (listado, el tipo de clase)'

Con este método, todos los artículos en su lista de edad se comprobará lo antes posible.

+0

¿'checkedList' en Java 5 no se aplica solo a listas genéricas nuevas (y vacías)? ¿Sugiere que usemos el 'checkList' no genérico antes de Java 5? Este formulario heredado no se convertirá en una lista genérica. –

0

Si acaba de emitir a List<T> en cualquier lugar anterior, recibirá una advertencia del compilador "no verificado". Resolvimos eso moviéndolo a un método de utilidad.

public class Lists { 
    @SuppressWarnings({"unchecked"}) 
    public static <T> List<T> cast(List<?> list) { 
     return (List<T>) list; 
    } 
} 

de llamadas ahora recibe ninguna advertencia, por ejemplo,:

for (Element child : Lists.<Element>cast(parent.getChildren())) { 
    // ... 
} 

Eso checkedList utilidad es en teoría una gran idea, pero en la práctica se aspira a tener que pasar en la clase que usted espera. Espero que Java obtenga eventualmente información de tipeo genérica en tiempo de ejecución.

1

Prueba esto:

List<ObjectType> objectsWithType = Arrays.asList((ObjectType[])wildcardObjects).toArray()); 

Pero recuerde que esto producirá una lista de longitud fija. Si intenta agregar o eliminar un elemento de esta lista, arrojará un error. Así que tenga siempre cuidado al usar Arrays.asList().

Cuestiones relacionadas