Saltar al contenido principal

Genéricos y Collections Framework

Un array de Object permite mezclar cualquier tipo, pero desplaza el error hasta la ejecución:

Object[] datos = {"Ana", 42};
String nombre = (String) datos[1]; // Compila, pero falla al ejecutarse.

El cast promete algo que el array no garantiza. Los genéricos permiten expresar el tipo aceptado y hacer que el compilador proteja esa decisión.

Un tipo como parámetro​

List<String> nombres = new ArrayList<>();
nombres.add("Ana");
String nombre = nombres.get(0);

String es el parámetro de tipo. La lista solo acepta cadenas y get devuelve una cadena sin cast. List<String> y List<Integer> son tipos distintos para el compilador.

Aquí usamos List solo para observar el modelo; sus operaciones se desarrollarán en JV3-02.

Seguridad en compilación​

List<String> nombres = new ArrayList<>();
nombres.add("Leo");
// nombres.add(10); // Error de compilación.

El genérico no existe solo para eliminar warnings: documenta una garantía y evita que entren valores incompatibles.

Evita los raw types:

List lista = new ArrayList(); // Pierde la garantía de tipo.

Primitivas y wrappers​

Los parámetros genéricos requieren tipos de referencia. Por eso List<int> no es válido; se utiliza List<Integer>. Las correspondencias más habituales son:

  • int → Integer
  • double → Double
  • boolean → Boolean

Java convierte automáticamente entre ambos cuando resulta posible:

List<Integer> cantidades = new ArrayList<>();
cantidades.add(3); // autoboxing: int → Integer
int primera = cantidades.get(0); // unboxing: Integer → int

El valor wrapper puede ser null; al hacer unboxing de null se produce un error. La comodidad no elimina esa diferencia.

El mapa mental del framework​

Collections Framework reúne interfaces y clases para organizar grupos de datos:

Collection
├── List → secuencia ordenada, admite duplicados
├── Set → elementos únicos
└── Queue → elementos pendientes según una política

Map → asociaciones clave → valor

Map no extiende Collection: no representa una colección de elementos aislados, sino asociaciones. Queue completa el mapa mental, pero no se desarrolla en este curso.

Interfaz frente a implementación​

List<String> nombres = new ArrayList<>();
  • List expresa las operaciones que necesita el código.
  • ArrayList es la implementación concreta que crea el objeto.

Programar contra la interfaz reduce la dependencia de una implementación. No significa que la implementación sea irrelevante: hay que elegir una que cumpla las necesidades.

Criterio inicial de elección​

  • Necesitas posición, orden y duplicados: List.
  • Necesitas unicidad: Set.
  • Necesitas buscar mediante una clave: Map.
  • Conoces un tamaño fijo y quieres una estructura sencilla: un array todavía puede ser adecuado.

Ejemplo completo​

import java.util.ArrayList;
import java.util.List;

public class GenericosDemo {
public static void main(String[] args) {
List<String> nombres = new ArrayList<>();
nombres.add("Ana");
nombres.add("Leo");

List<Integer> puntos = new ArrayList<>();
puntos.add(10);
puntos.add(15);

int total = puntos.get(0) + puntos.get(1);
System.out.println(nombres.get(0));
System.out.println(total);
}
}

Errores habituales​

  • Usar List sin parámetro de tipo.
  • Intentar declarar List<int>.
  • Introducir casts para compensar un diseño sin tipos.
  • Confundir List con el objeto concreto ArrayList.
  • Creer que Map forma parte de Collection.

Practica: inventario tipado​

Enunciado y criterios​

Crea una lista de códigos String y otra de cantidades Integer. Añade dos valores a cada una y muestra el primer código junto con su cantidad. No uses raw types ni casts.

Solución​

import java.util.ArrayList;
import java.util.List;

public class InventarioTipado {
public static void main(String[] args) {
List<String> codigos = new ArrayList<>();
List<Integer> cantidades = new ArrayList<>();

codigos.add("T-01");
codigos.add("R-02");
cantidades.add(4);
cantidades.add(7);

System.out.println(codigos.get(0) + ": " + cantidades.get(0));
}
}

Cada lista ofrece una garantía distinta. En la siguiente unidad aprenderemos a modificar y recorrer secuencias dinámicas con List.