Command Palette

Search for a command to run...

ES·EN

Nivel 2 · 20 min

Genéricos y Sistemas de Tipos

Los genéricos en Java permiten escribir código con tipos parametrizados, evitando casts y errores de tipo en runtime. Pero tienen una particularidad fundamental: type erasure. El compilador verifica los tipos en compile-time y luego los borra — en runtime, List'<'String'>' y List'<'Integer'>' son la misma clase List.

Type safety y type erasure

Sin genéricos, List aceptaba cualquier Object y los bugs de tipo aparecían en runtime con ClassCastException. Con genéricos, List'<'String'>' garantiza que solo contendrá Strings — el compilador previene el error. Type erasure: en runtime, los parámetros genéricos no existen. List'<'String'>' en bytecode es solo List. Implicación: no podés hacer new T(), instanceof List'<'String'>' (solo instanceof List), o métodos estáticos que dependan de T en instancias.

Wildcards y varianza

El wildcard ? representa un tipo desconocido. List'<'?'>' es una lista de algún tipo. PECS (Producer Extends, Consumer Super): si una lista produce (leés de ella), usá extends — List'<'? extends Animal'>'. Si consume (escribís en ella), usá super — List'<'? super Dog'>'. Covarianza en Java: List'<'Dog'>' NO es subtipo de List'<'Animal'>', aunque Dog sea subtipo de Animal — para eso usás List'<'? extends Animal'>'.

Bounded generics y varianza en OOP

Los bounded type parameters ('<'T extends Comparable'<'T'>''>') limitan qué tipos puede tomar T. Los wildcards bounded (List'<'? extends Shape'>') son más flexibles para APIs. En OOP, la varianza es importante para colecciones polimórficas. Arrays son covariantes (String[] es subtipo de Object[]) — esto puede llevar a ArrayStoreException en runtime. Los genéricos son invariantes por default, lo que es más seguro.

Puntos clave

  • Type erasure significa que la información genérica solo existe en compile-time — no podés acceder a ella en runtime.
  • PECS: Producer Extends, Consumer Super. Lista de la que leés → extends. Lista en la que escribís → super.
  • List'<'Dog'>' no es subtipo de List'<'Animal'>' — los genéricos son invariantes. Usá List'<'? extends Animal'>' para covarianza.

Code example

// PECS en accion
<T> void copy(List<? extends T> src, List<? super T> dest) {
  for (T item : src) dest.add(item);
}
// Funciona: copy(dogs, animals) donde dogs: List<Dog>, animals: List<Animal>
// dogs produce Dog (extends), animals consume Dog (super)