Course outline · 0% complete

0/29 lessons0%

Course overview →

Writing generic code

lesson 8-1 · ~6 min · 22/29

Quiz

Warm-up from lesson 7-1: what does the <String> in ArrayList<String> buy you?

Type parameters

Before Java 5, collections held plain Objects: you could put a String into a list of what you thought were Integers, and nothing complained until some distant line cast it back and crashed at runtime — in production, far from the actual mistake. Generics were added to move that entire class of bug to compile time, and they are why ArrayList<String> can promise what it holds. Here is the mechanism from the inside.

Suppose you write a Box class that holds one item. A StringBox, an IntBox, a DogBox... copies everywhere. Generics let you write it once with a placeholder type:

class Box<T> {
  private T item;

  void put(T item) {
    this.item = item;
  }

  T get() {
    return item;
  }
}

T is a type parameter, a stand-in filled at use time: Box<String> makes every T mean String, Box<Integer> makes it Integer. This is exactly how ArrayList<E> and HashMap<K, V> are written in the standard library. The compiler enforces each choice: a Box<String> will not accept an Integer.

Code exercise · java

Run this. One Box class serves two element types. Try adding stringBox.put(42) to see the compiler protect you, then remove it.

Generic methods

A single method can be generic too. Declare the parameter before the return type:

static <T> T firstOf(ArrayList<T> list) {
  return list.get(0);
}

Call it normally: firstOf(names) where names is an ArrayList<String> returns a String. Java infers T from the argument.

Conventions: T for a general type, E for a collection element, K/V for key and value. And a limitation you already met in lesson 7-1 applies here: type arguments must be object types, so Box<int> is invalid, use Box<Integer>.

Quiz

stringBox is a Box<String>. What happens on stringBox.put(42)?

Code exercise · java

Your turn. Write a generic class Pair<A, B> holding two fields, with a constructor and a toString returning `(<first>, <second>)`. Print a Pair of "age" and 30, then a Pair of 1 and 2.