---
title: "Generics and type safety"
chapter: "05"
---

# Generics and type safety

Generics let one type or method work with a family of types while preserving
compile-time safety.

## Parameterized types

`List<String>` means a list that accepts strings. Generic types are invariant:
`List<Integer>` is not a subtype of `List<Number>`, because otherwise someone
could add a `Double` to the integer list.

## Bounds and wildcards

- `<T extends Comparable<T>>`: a type parameter with an upper bound.
- `? extends Number`: producer of some unknown Number subtype.
- `? super Integer`: consumer that can safely accept Integer.
- `?`: unknown type when only Object-level behavior is required.

Remember PECS: **Producer Extends, Consumer Super**.

```java
static double sum(List<? extends Number> values) { ... }
static void addDefaults(List<? super Integer> target) { ... }
```

## Generic methods

The type parameter appears before the return type:
`static <T> T first(List<T> values)`. Type inference normally determines `T`.

## Erasure

Most generic type arguments are erased from runtime representation. You cannot
create `new T()`, use `T.class`, create generic arrays directly, or reliably
test `instanceof List<String>`. Bridge methods may preserve polymorphism after
erasure.

## Raw types and heap pollution

Raw `List` bypasses generic checks and can move failure to a later cast.
Varargs of generic types can create heap pollution; use `@SafeVarargs` only
when the method is genuinely safe and eligible.

## Feynman check

Generics are labels enforced at the warehouse entrance. Erasure means many
labels are removed before delivery, so the runtime often sees only the box
shape, not the original label.
