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:
- Ensanchamiento
- Boxeo
- 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.