Step 1 of 5 · Reading · ~2 min
Learn
Generics and Collections
Generics let you write code that works with different types without losing type safety. Replaces the old Object + cast pattern.
List<String> names = new ArrayList<>();
names.add("Ada");
String first = names.get(0); // no cast, no ClassCastException
Generic class:
class Box<T> {
private T value;
public Box(T value) { this.value = value; }
public T get() { return value; }
}
Box<Integer> intBox = new Box<>(42);
Box<String> strBox = new Box<>("hi");
Generic method:
public static <T> T firstOf(List<T> list) {
return list.get(0);
}
Bounded type parameters — restrict T:
public static <T extends Comparable<T>> T max(List<T> list) {
T m = list.get(0);
for (T x : list) if (x.compareTo(m) > 0) m = x;
return m;
}
Wildcards:
List<?>— unknown type (read-only essentially)List<? extends Number>— Number or any subclass (covariant read)List<? super Integer>— Integer or any supertype (contravariant write)
Mnemonic: PECS — Producer Extends, Consumer Super.
Declaring a generic class in a single-file program
The exercises here compile one file with a Main class, so a helper like
Pair<A, B> has to live inside it — and it must be declared static:
public class Main {
static class Pair<A, B> { // static: belongs to the class
private final A first;
private final B second;
Pair(A first, B second) { this.first = first; this.second = second; }
}
public static void main(String[] args) {
Pair<String, Integer> p = new Pair<>("Ada", 36); // compiles
}
}
Drop the static and the compiler says non-static variable this cannot be
referenced from a static context: a non-static inner class belongs to an
instance of Main, and main never creates one. The type parameters
A and B are also types, not fields — this.first, never this.A.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…