2011-05-18 17 views
7

¿Puede alguien explicarme por qué la línea marcada //this line gives a compile error (why?) en el siguiente ejemplo de código no funciona?¿Por qué no funciona el lanzamiento de un genérico de ArrayList a una superclase?

import java.util.ArrayList; 

public class GenericCastCheck { 

    class A{ 
    } 

    class B extends A{ 
    } 

    public static void main(String[] args) { 

     A aObject = new A(); 
     B bObject = new B(); 

     //this line works fine 
     aObject = bObject; 
     //this line gives a compile (expected) 
     bObject = aObject; 

     ArrayList<A> aList = new ArrayList<A>(); 
     ArrayList<B> bList = new ArrayList<B>(); 

     //this line gives a compile error (why?) 
     aList = bList; 
     //this line gives a compile error (expected) 
     bList = aList; 
    } 
} 

En concreto, cuando se dice que es de tipo bListArrayList<B>, ¿No significa que cada elemento de la misma es una instancia de B? Si es así, ¿cuál es el problema al convertirlo a ArrayList<A>, si podemos convertir instancias individuales de B en A?

Gracias.

Respuesta

10

El problema es el siguiente:

ArrayList<A> aList = new ArrayList<A>(); 
ArrayList<B> bList = new ArrayList<B>(); 
aList = bList; // if this were valid... 
aList.add(new A()); // ...what should happen here? 
B b = bList.get(0); // ...and here? 

Si lo hace lo mismo con las matrices, se obtiene una ArrayStoreException en la línea 4 en tiempo de ejecución. Para colecciones genéricas, se decidió evitar ese tipo de cosas en tiempo de compilación.

+0

Muchas gracias. Me di cuenta de que debería usar 'aList = new ArrayList (bList);' en lugar de 'aList = bList', que también se compila bien. :) – Animesh

5

Porque genéricos son estrictos. no se covarient

ArrayList<A> aList sólo puede referirse a un tipo de ArrayListA


De wiki

A diferencia de los arrays, clases genéricas son ni covariante ni contravariante. Por ejemplo, ni List<String> ni List<Object> es un subtipo de la otro:

// a is a single-element List of String 
List<String> a = new ArrayList<String>(); 
a.add("foo"); 

// b is a List of Object 
List<Object> b = a; // This is a compile-time error 

Sin embargo, los parámetros de tipo genérico puede contener comodines (un acceso directo para un parámetro de tipo adicional que es utilizado una vez). Ejemplo: Dado un requisito de un método que opera en Listas, de cualquier objeto, entonces la única operaciones que se pueden realizar en el objeto son aquellos para los que los relaciones de tipo se pueden garantizar para estar seguro.

// a is a single-element List of String 
List<String> a = new ArrayList<String>(); 
a.add("foo"); 

// b is a List of anything 
List<?> b = a; 

// retrieve the first element 
Object c = b.get(0); 
// This is legal, because we can guarantee 
// that the return type "?" is a subtype of Object 

// Add an Integer to b. 
b.add(new Integer (1)); 
// This is a compile-time error; 
// we cannot guarantee that Integer is 
// a subtype of the parameter type "?" 

Los comodines también pueden vincularse, p. Ej. "? extends Foo" o "? super Foo" para límites superior e inferior, respectivamente. Esto permite refinar el rendimiento permitido. Ejemplo: dado un List<? extends Foo>, un elemento puede ser recuperado y asignado de manera segura a un tipo Foo (covarianza). Dado un List<? super Foo>, entonces un objeto Foo puede ser agregado con seguridad como un elemento (contravarianza).

0

Animesh,

A pesar de que la clase B es subtipo de A, B ArrayList <> no es un subtipo de ArrayList < A>. Está en la misma línea que en B [] no es subtipo de A []. Estos son dos tipos independientes no relacionados.

+2

En realidad, B [] * es * un subtipo si A [] ... –

0

Porque hay ninguna relación subtipo en Java entre C<A> y C<B>, incluso si A es un supertipo de B o viceversa.

Si está interesado en la búsqueda de detalles co/contra-varianza en Wikipedia.

Tenga en cuenta, que en las matrices de Java son co-variante, lo que significa A[] es un supertipo de B[] si A es un supertipo de B. Esa es la razón por la que a veces obtienes extraños cast de excepción con matrices.

Cuestiones relacionadas