2011-05-23 15 views
12

Considere este ejemplo:¿Por qué los tipos crudos en un lugar causan callites genéricos en otro lugar para ser tratados como crudos?

import java.util.*; 

class Foo<T> { 
    public int baz(List<String> stringlist) { return 1; } 
    public int baz(ArrayList<Object> objectlist) { return 2; } 

    public static void main(String[] args) { 
    Foo<String> foo = new Foo<String>(); // (A) 
    //Foo foo = new Foo();    // (B) 

    System.out.println(foo.baz(new ArrayList<String>())); 
    } 
} 

¿Por qué se imprime en 1(A), pero 2 con (B)?

Sé cómo funciona la resolución de métodos, así que no hay necesidad de explicarme eso.

Quiero saber la motivación más profunda detrás de esta "función". ¿Por qué no hay una advertencia de borrado al respecto? (Solo hay uno sobre Foo foo = new Foo().)

¿Por qué la resolución del método utiliza semántica borrada aunque se proporciona el tipo genérico?

Respuesta

5

Es porque cuando el compilador es resolving overloads, considera cada método, ya sea como genérico o no genérico, nunca una mezcla de los dos, por lo que los candidatos son:

  1. Foo<T>.baz(List<String>)
  2. Foo<T>.baz(ArrayList<Object>)

si foo es una Foo<String> o

  1. Foo.baz(List)
  2. Foo.baz(ArrayList)

si foo es una Foo.

No existe tal cosa como Foo.baz(List<String>). O bien se consideran todos los parámetros de tipo o ninguno. (No estoy al tanto de que esto se establezca explícitamente en el JLS, pero tiene sentido ya que tratar un método genérico como si fuera el equivalente bruto es una característica de compatibilidad con versiones anteriores.)

En el primer caso, Foo<T>.baz(List<String>) coincide pero Foo<T>.baz(ArrayList<Object>) no.

En el segundo caso ambas funciones coinciden, y Foo.baz(ArrayList) es more specific, por lo que se elige.

0

Ni siquiera compilará el caso (A) si solo conserva el único método (error: el método no se puede aplicar al tipo dado). Supongo que ArrayList<String> no es una subclase de ArrayList<Object>.

Es extraño que se compile en el caso (B), pero deben haber tomado algunas decisiones raras para mantener la compatibilidad con colecciones no genéricas.

+4

Sure it is not. El tipo de elemento 'ArrayList' no está definido como covariante. – soc

Cuestiones relacionadas