2012-06-20 13 views
7
public void addAllAnimals(ArrayList<? extends Animal> animalLikeList){ 

// I need to add animal objects (eg Dog, Cat that extends Animal) to animalLikeList. 

} 

sé que no permite añadir directamente desde ? extends Animal representa el tipo de sub desconocido de la Animal.

Mi pregunta es: ¿hay alguna manera (manera indirecta) de add o addAll un Animal o un subtipo de Animal objeto para el animalLikeList?agregar objetos al "? Extiende" tipo de genérica Colecciones

+0

No conseguir su pregunta? –

+0

Lo edité Akhil. Quiero saber si hay alguna forma (cualquier forma maliciosa) de agregarle elementos. ¡O es realmente IMPOSIBLE! – namalfernandolk

+0

¿Por qué usas el comodín si pretendes infringir su restricción, simplemente no tiene sentido? –

Respuesta

8

No, no hay manera legal directa (aparte de moldes de tipo inseguro). Solo puede agregar elementos a una colección genérica declarada con super, no extends. Esto puede ser más fácil de recordar con las siglas PECS (productor - se extiende, al Consumidor - súper), popularizada por Josh Bloch en Effective Java, 2ª Edición, artículo 28.

De hecho lo que parece ser después no parece tener sentido directo. Un List<? extends Animal> puede ser, p. a List<Dog> o List<Cat>. El primero solo puede aceptar Dog elementos, el último solo Cat s. Y dado que no puede crear instancias de tipos genéricos (no identificables) en Java, debe saber en tiempo de ejecución que está tratando con una lista de perros, por lo que solo intenta agregarle perros (y viceversa para los gatos). Eso significa que no puede crear de forma local y estática los objetos que se agregarán; también debe obtenerlos de una manera genérica y, además, de una manera que le permita al compilador asegurarse de que los tipos concretos coincidan cada vez. La forma más sencilla de hacerlo es pasar el elemento (s) como un parámetro genérico. Por lo que es posible y segura de hacer esto:

public <E extends Animal> void addAllAnimals(List<E> animalLikeList, E animal) { 
    animalLikeList.add(animal); 
} 

List<Dog> dogs = new ArrayList<Dog>(); 
List<Cat> cats = new ArrayList<Cat>(); 

addAllAnimals(dogs, new Dog()); 
addAllAnimals(cats, new Cat()); 

Tenga en cuenta que este método es genérico, con un parámetro de tipo de llamada, lo que garantiza que el tipo genérico real de la lista es el mismo que el tipo de elemento que se añade lo.

Puede reemplazar trivialmente el parámetro E con Collection<E> para agregar varios objetos a la vez.

+0

+1 por E extiende Animal – namalfernandolk

4

Mi pregunta es: ¿no hay forma (manera indirecta) de agregar o agregar a AnimalLikeList todos los objetos de Animal o Subtipo de Animal?

No sin cambiar la firma, y ​​por una buena razón. Supongamos que desea añadir Dog valores a esa lista ... pero supongo que es lógicamente una lista de los gatos:

ArrayList<Cat> cats = new ArrayList<Cat>(); 
addAllAnimals(cats); 

No debe ser capaz de añadir un Dog a un ArrayList<Cat>, debe usted?

Si usted quiere ser capaz de añadir cualquier tipo de animal a la lista, es necesario:

public void addAllAnimals(ArrayList<Animal> animalLikeList) { 

o

public void addAllAnimals(ArrayList<? super Animal> animalLikeList) { 
+0

Gracias Jon. Pero estoy pasando diferentes listas de animales (ArrayList , ArrayList ) al método addAllAnimals. Es por eso que estoy usando addAllAnimals (ArrayList . – namalfernandolk

+2

@NamalFernando: Entonces, ¿cómo esperas agregar un 'Perro' a la lista dentro de' addAllAnimals'? ¿Qué quieres * que suceda si tratas de agregar un 'Perro' a un' ArrayList '¿Ves cómo tienes un problema fundamental allí? –

+1

@NamalFernando Jon prácticamente ha dicho todo lo que hay que decir al respecto. No hay forma segura de agregar a un lista con ese tipo de tipo. – Kallja

0
ArraList<anything extends animal> list= new ArrayList<anything extends animal>(); 


addAllAnimals(list); 

Esto es perfectamente válido. su método addAllAnimals aceptará cualquier arrayList que declare contener cualquier subtipo de Animal.

y para agregar un objeto/Lista, puede cualquier objeto/lista qué subtipo de Animal.

+0

No creo que esto compile bien –

+0

, en lugar de "todo se extiende animal" puede haber perro, gato, etc. No veo ninguna razón por la cual no compilará – Ahmad

0

No de una manera typesafe ...

Una idea sería cambiar la firma a:

public static <T extends Animal> void addAllAnimals(ArrayList<? super T> list){} 

donde se puede añadir T o subtipos de T a una lista de T ...

1

¿Por qué no simplemente cambia la firma del método para usar un parámetro de tipo invariante?

public void addAllAnimals(ArrayList<Animal> animalLikeList){ 
    animalLinkedList.add(new Dog()); 
    animalLinkedList.add(new Cat()); 

} 

Se debe trabajar muy bien, y mediante el uso de un parámetro de tipo de invariante se le permitirá leer de la lista o escribir en él, y por las reglas de pollymorphism subtipo que puede contener cualquier tipo de animal que se querer.

En lugar de intentar pasar la lista de perros o la lista de gatos, pase la lista de animales al método.

0

Se puede utilizar una forma no genérico para addAll en una colección genérica

public void testExtends(ArrayList<? extends Parent> list) throws Exception { 
    /* list.add(new Child()); 
     list.add(new Parent()); 
     list.add(new GrandParent()); 
     // can not add 
     */ 
     /** 
     * Unsafe collection way 
     */ 
     ArrayList list2=new ArrayList(); 
     list.addAll(list2); 
    } 
Cuestiones relacionadas