Command Palette

Search for a command to run...

ES·EN

Nivel 2 · 20 min

Generics

Los generics de Java habilitan colecciones y algoritmos type-safe en tiempo de compilación. Entender el borrado de tipos, los wildcards acotados y el principio PECS es esencial para escribir código de librería reutilizable y evitar sorpresas de ClassCastException en runtime.

Borrado de tipos y tipos reificables

Los generics de Java usan borrado de tipos: los parámetros de tipo genérico se eliminan en tiempo de compilación y se reemplazan con Object (o el límite superior para tipos acotados). Esto es para compatibilidad con bytecode pre-generics. Consecuencia: List'<'String'>' y List'<'Integer'>' son el mismo tipo en runtime — no podés hacer instanceof List'<'String'>' ni crear new T[]. Los tipos reificables son tipos cuya información de tipo completa está disponible en runtime.

Wildcards acotados: ? extends T / ? super T

? extends T (acotado superiormente) significa "algún tipo que es T o un subtipo de T". ? super T (acotado inferiormente) significa "algún tipo que es T o un supertipo de T". Insight clave: podés LEER de una colección ? extends T (obtenés al menos un T), pero NO podés ESCRIBIR en ella. Podés ESCRIBIR en una colección ? super T, pero obtenés Object cuando LEES. Esta asimetría es PECS.

PECS: Producer Extends, Consumer Super

PECS (Producer Extends, Consumer Super) es la regla para elegir wildcards. Usá ? extends T cuando el tipo parametrizado es un productor — estás leyendo (produciendo) valores de él. Usá ? super T cuando el tipo parametrizado es un consumidor — estás escribiendo (consumiendo) valores en él. Ejemplo: Collections.copy(List'<'? super T'>' dest, List'<'? extends T'>' src) — src produce T (extends), dest consume T (super).

Puntos clave

  • Borrado de tipos: los tipos genéricos pierden sus parámetros de tipo en runtime. Sin verificaciones instanceof en tipos genéricos, sin arrays genéricos.
  • PECS — Producer Extends, Consumer Super. Si leés de él, usá ? extends. Si escribís en él, usá ? super.
  • ? (wildcard sin acotar) significa que el tipo es desconocido. Solo podés leer Object de él y no podés escribir nada (excepto null).

Code example

// Borrado de tipos — ambas son List en runtime
List<String> strings = new ArrayList<'>();
List<Integer> ints = new ArrayList<'>();
// strings.getClass() == ints.getClass() → true!

// PECS: copiar desde productor (extends) hacia consumidor (super)
public static <T> void copy(
    List<? super T> dest,
    List<? extends T> src) {
  for (T item : src) dest.add(item);
}

// Método genérico: funciona para cualquier tipo Comparable
public static <T extends Comparable<T>'> T max(List<T> list) {
  T result = list.get(0);
  for (T item : list)
    if (item.compareTo(result) > 0) result = item;
  return result;
}

// No se puede crear un array genérico — error de compilación:
// T[] arr = new T[10]; // ERROR: generic array creation