2010-11-12 21 views
16

En Java, cuando se lanza desde un objeto a otros tipos, ¿por qué la segunda línea produce una advertencia relacionada con el molde, pero la primera no?Java: Casting Object a un tipo genérico

void a(Object o) { 
    Integer i = (Integer) o; 
    List<Integer> list = (List<Integer>) o; 
} 

/*Type safety: Unchecked cast from Object to List<Integer>*/ 
+0

La segunda línea produce una advertencia porque solo los genéricos generan dicha advertencia. El primero no contiene ningún genérico, por lo tanto, no hay advertencia. –

Respuesta

24

Es porque el objeto no realmente comprobarse por ser un tiempo List<Integer> en ejecución debido al tipo borrado. Realmente solo lo lanzará al List. Por ejemplo:

List<String> strings = new ArrayList<String>(); 
strings.add("x"); 
Object o = strings; 

// Warning, but will succeeed at execution time 
List<Integer> integers = (List<Integer>) o; 
Integer i = integers.get(0); // Bang! 

Ver Angelika Langer's Java Generics FAQ para obtener más información, en particular el type erasure section.

5

La respuesta de Jon es la correcta, pero ocasionalmente no se puede evitar esa advertencia (como cuando se trabaja con una API heredada). En esos casos se puede suprimir la advertencia de este modo:

@SuppressWarnings("unchecked") 
List<Integer> list = (List<Integer>) someApiThatReturnsNonGenericList(); 
6

Para mayor claridad, permítanme volver a escribir un poco los ejemplos ...

yo diría, la diferencia entre cruxial:

void a(Object o) { 
    Integer i = (Integer) o; 
    ... 
} 

y

void a(Object o) { 
    List<Integer> list = (List<Integer>) o; 
    ... 
} 

es que, dado que hay un error de tipo, el primer elenco siempre arroja inmediatamente una RuntimeException (específicamente, una ClassCastException) cuando se ejecuta.

mientras que el segundo podría no - siempre y cuando el parámetro de entrada o algún tipo de List<?>, la ejecución se acaba de proceder, a pesar de un lanzamiento incorrecto.

Si el código en algún lugar más tarde lanza una excepción o no, depende de lo que haga con la lista.

Pero independientemente, una excepción podría no arrojarse a la línea donde se hizo el elenco, pero en otro lugar (que podría ser un error difícil de rastrear) o en absoluto.

Eso es lo que entiendo, es la razón por la que los compiladores y diseñadores consideraron una advertencia apropiada solo en el segundo caso.

+1

Excelente explicación. – Trilarion

+0

La primera * no * arrojará siempre una CastClassException. El objeto entrante podría ser un 'Entero '. La primera línea PUEDE arrojar una excepción, igual que la segunda si 'o' no es una' Lista '. –

+0

@Hot Licks: sí, es por eso que escribí "dado que hay un error tipográfico" arriba, incluso lo puse en negrita;) – Rop

Cuestiones relacionadas