java generics polymorphism parametric-polymorphism

Polimorfismo avanzado en Java



generics polymorphism (3)

Tengo clases de programación avanzada en mi universidad y tengo algunos problemas para entender cómo funciona este código.

public final class GenericClass<T> { private void overloadedMethod(Collection<?> o) { System.out.println("Collection<?>"); } private void overloadedMethod(List<Number> o) { System.out.println("List<Number>"); } private void overloadedMethod(ArrayList<Integer> o) { System.out.println("ArrayList<Integer>"); } public void method(List<T> l) { overloadedMethod(l); } public static void main(String[] args) { GenericClass<Integer> test = new GenericClass<Integer>(); test.method(new ArrayList<Integer>()); } }

¿Por qué este código se imprime "Colección <?>"?


Cuando defina un tipo genérico, se proporcionará automáticamente un tipo sin procesar correspondiente. Este método

public void method(List<T> l) { }

está reemplazando con

public void method(List<Object> l) { }

Si lees sobre los tipos de comodines, verás que List<Number> y List<Object> o ArrayList<Integer> y List<Object> no tienen ningún tipo de relación. List<Object> es un subtipo de Collecion<?> Por lo que se llama a este método.


Cuando lidias con la sobrecarga de métodos debes poner tres conceptos en tu mente:

  1. Ensanchamiento
  2. Boxeo
  3. Var_args

su problema radica en el primer punto que se está ampliando, el compilador java le da prioridad a cada uno de estos conceptos en el mismo orden en el que se enumeran anteriormente, por lo que prefiere la ampliación y cuando llama a su método como test.method(new ArrayList<Integer>()); el compilador encuentra que ArrayList<Integer>() podría ampliarse a la Collection<?> y como tiene la prioridad más alta, llama a estas versiones y descuida las otras. Nota: si cambia la declaración de los otros dos métodos a private void overloadedMethod(ArrayList<?> o) y private void overloadedMethod(List<?> o) el compilador también llamará la versión de Collection<?> Porque es la preferida


La declaración de method(List<T> l) no especifica ningún límite en el tipo T. No hay garantía de que T sea Número o una subclase de Número. Por lo tanto, el compilador solo puede decidir que este método llame a overloadedMethod(Collection<?> o) .

Recuerde: después de la compilación, la información sobre genéricos ya no está disponible en los archivos de clase.