# One class, and the types are gone

`corpus/shopping-cart/reference/src/` holds the same registry twice. `Catalog` maps a code to a
`Sku`, `CouponBook` maps a code to a `Promotion`, and both are a map plus a `require(code)` that
throws for an unknown code. One type parameter collapses them into one file:

```java
public final class CodeIndex<T> {
    private final Map<String, T> byCode;
    public T require(String code) { ... }
}
```

A template would hand you two classes here, `CodeIndex<Sku>` and `CodeIndex<Promotion>`, each
generated separately and each knowing its own `T`. Java hands you one. `javap -s` on what it
compiled:

```
public T require(java.lang.String);
  descriptor: (Ljava/lang/String;)Ljava/lang/Object;
```

`T` became `Object`. The caller got a cast nobody wrote:

```
3: invokevirtual #9   // Method CodeIndex.require:(Ljava/lang/String;)Ljava/lang/Object;
6: checkcast     #15  // class Sku
```

That is erasure, and it is the whole lesson: one class with `Object` in it, and a cast at every
call site.

The first thing it costs is smaller than that machinery suggests. `Catalog.require` says
`no such sku: NOPE`, `CouponBook.require` says `no such coupon: SAVE99`, and the grader asserts
both. So `CodeIndex.require` needs the name of `T` — which the descriptor above no longer carries.
There is nowhere to read it from. It has to arrive as data:

```java
new CodeIndex<>("sku", byCode)
```

That missing string is the shape of everything else on this page. No `new T()`. No `new T[n]`. A
`static` field shared by every parameterisation, because there is one class holding it. And no
`List<int>`, so a quantity in a map is an `Integer`, and an `Integer` can be null.
