Historia de la pregunta:
Los generics en Java fueron introducidos en Java 5 para garantizar un trabajo seguro con tipos de colecciones y métodos, pero se implementaron con el soporte de la compatibilidad hacia atrás con el bytecode ya existente. Para esto, se aplicó un mecanismo de eliminación de tipos.
Problema:
El compilador de Java requiere una tipificación estricta, sin embargo, en tiempo de ejecución la JVM no conoce los parámetros de tipificación, y muchas clases y bibliotecas antiguas, incluida la propia biblioteca de colecciones de Java, trabajan con tipos "crudos" (raw types). Sin la compatibilidad hacia atrás, no se podía mantener el desarrollo existente.
Solución:
La eliminación de tipos es el proceso de convertir tipos parametrizados (generics) a sus versiones "crudas", para que la JVM pueda trabajar con el bytecode existente sin cambios. Toda la información sobre los parámetros de tipo se elimina en la etapa de compilación, y en su lugar se utilizan objetos del tipo Object (o una restricción, si se indica a través de extends).
Ejemplo de código:
List<String> stringList = new ArrayList<>(); stringList.add("hola"); String s = stringList.get(0); // get devuelve Object, pero el compilador inserta cast
Características clave:
List<String>, List<Integer>, etc.¿Se puede usar la sobrecarga de métodos solo por los parámetros de generics?
No. Debido a la eliminación de tipos, el compilador considera que los métodos con los mismos nombres y diferentes parámetros de generics son idénticos, ya que los parámetros serán eliminados. Por ejemplo,
// ¡Error de compilación! void process(List<String> list) { } void process(List<Integer> list) { }
¿Se puede crear un array de tipo genérico?
No directamente. La eliminación de tipos no permite que la JVM almacene un array de un tipo genérico específico, por ejemplo,
List<String>[] array = new List<String>[10]; // ¡Error de compilación!
Se puede evitar con un array de tipos crudos, pero esto no es seguro:
List<String>[] array = (List<String>[]) new List[10];
¿Se puede verificar el tipo de un genérico en tiempo de ejecución a través de instanceof?
No, ya que la información sobre los parámetros se elimina. La comprobación:
if (obj instanceof List<String>) { ... } // ¡Error de compilación!
Lo correcto sería verificar solo el tipo base:
if (obj instanceof List) { ... }
Un programador crea un array de tipos parametrizados para almacenar listas de diferentes parámetros. Al final, después de un largo tiempo de ejecución del programa, se produce un ClassCastException al extraer un objeto del array: la tipificación en tiempo de ejecución no se garantiza.
Ventajas:
Desventajas:
En lugar de arrays, se utilizan colecciones (por ejemplo, List<List<String>>), y todas las comprobaciones de tipos se delegan al compilador.
Ventajas:
Desventajas: