← Back to Java series
πŸ“¦
Collections & Generics
Collections & Generics Β· Prerequisite: previous lecture

13. Generics and Wildcards

Generics make collections and methods **type-safe and reusable**. This lecture covers generic classes / methods, the wildcards `?`, `? extends`, `? super`, and the limits caused by type erasure.

JavagenericswildcardPECS
Duration
⏱ ~1.5-2 hours
Level
πŸ“Š Intermediate
Prerequisite
🎯 Previous lecture or equivalent knowledge
OUTCOME
Generics make collections and methods **type-safe and reusable**. This lecture covers generic classes / methods, the wildcards `?`, `? extends`, `? super`, and the limits caused by type erasure.

What you'll learn

  • 1Declare a generic class or method
  • 2Apply the wildcards `? extends T`, `? super T`
  • 3Understand PECS (Producer Extends, Consumer Super)
  • 4Understand the limits of type erasure

Overview

Generics make collections and methods **type-safe and reusable**. This lecture covers generic classes / methods, the wildcards `?`, `? extends`, `? super`, and the limits caused by type erasure.

Core Concepts

1) Generic class

java
public class Box<T> {
    private T value;
    public void set(T value) { this.value = value; }
    public T get() { return value; }
}

Box<String> b = new Box<>();
b.set("hello");
String s = b.get();    // no cast needed

2) Generic method

java
static <T> T firstOf(java.util.List<T> list) {
    return list.isEmpty() ? null : list.get(0);
}

3) Wildcards

java
List<? extends Number> nums = List.of(1, 2.0, 3L);
double sum = 0;
for (Number n : nums) sum += n.doubleValue();   // read OK
// nums.add(4);    // compile error β€” write forbidden

**`? extends T`** = read-only producer. **`? super T`** = write-only consumer.

4) PECS

**P**roducer **E**xtends, **C**onsumer **S**uper: if you only read use `extends`; if you only write use `super`.

5) Type erasure

At runtime, generic type information is **erased**. `List<String>` and `List<Integer>` are the same class at runtime, so `instanceof List<String>` is illegal.

Examples

Example 1 β€” `BoxDemo.java`

java
public class BoxDemo {
    static class Box<T> {
        private T value;
        void set(T v) { value = v; }
        T get() { return value; }
    }

    public static void main(String[] args) {
        Box<String> sb = new Box<>();
        sb.set("hello");
        System.out.println(sb.get());

        Box<Integer> ib = new Box<>();
        ib.set(42);
        System.out.println(ib.get());
    }
}

**Output**

text
hello
42

Example 2 β€” `FirstOf.java`: generic method

java
import java.util.List;

public class FirstOf {
    static <T> T firstOf(List<T> list) {
        return list.isEmpty() ? null : list.get(0);
    }

    public static void main(String[] args) {
        System.out.println(firstOf(List.of("a", "b")));
        System.out.println(firstOf(List.of(1, 2, 3)));
    }
}

**Output**

text
a
1

Example 3 β€” `PecsDemo.java`

java
import java.util.ArrayList;
import java.util.List;

public class PecsDemo {
    static double sumOf(List<? extends Number> nums) {   // producer
        double s = 0;
        for (Number n : nums) s += n.doubleValue();
        return s;
    }

    static void addInts(List<? super Integer> sink) {     // consumer
        sink.add(1);
        sink.add(2);
    }

    public static void main(String[] args) {
        List<Integer> ints = List.of(1, 2, 3);
        System.out.println(sumOf(ints));

        List<Number> dest = new ArrayList<>();
        addInts(dest);
        System.out.println(dest);
    }
}

**Output**

text
6.0
[1, 2]

Example 4 β€” `Erasure.java`

java
import java.util.ArrayList;
import java.util.List;

public class Erasure {
    public static void main(String[] args) {
        List<String> a = new ArrayList<>();
        List<Integer> b = new ArrayList<>();
        System.out.println(a.getClass() == b.getClass());   // true!
    }
}

**Output**

text
true

**Note:** both are `ArrayList` at runtime β€” the generic parameter is erased.

Common Mistakes

  1. Trying `new T[10]` β€” illegal because of erasure
  2. Using `instanceof List<String>` β€” illegal
  3. Writing to a `List<? extends T>` (allowed reads only)
  4. Reading a specific type from `List<? super T>` (you can only read as `Object`)
  5. Using raw types (`List`) instead of parameterized types β€” loses type-safety warnings

Summary

  • Generics give you type safety at compile time
  • PECS: producer β†’ `extends`, consumer β†’ `super`
  • Type erasure means runtime type info is lost

Practice

# Practice - 13. Generics

## Exercise 1 β€” `Pair<A, B>`

  • File: `Homework01.java`
  • Key concepts: two type parameters

Requirements

  • Class `Pair<A, B>` with `A first`, `B second`, and a `toString()` returning `(a, b)`.
  • Create `Pair<String, Integer>("Jisoo", 21)` and print it.

Expected output

text
(Jisoo, 21)

## Exercise 2 β€” `sumOf` with `? extends Number`

  • File: `Homework02.java`
  • Key concepts: bounded wildcard

Requirements

  • Static `double sumOf(List<? extends Number> list)`.
  • Call with `List<Integer>` and `List<Double>` lists.

Expected output

text
ints=6.0
doubles=4.5

## Solutions After trying it yourself, compare with [`answer/`](./answer/).

Solution code (homework/answer/)

answer/Homework01.java

java
/** Pair<A, B>. */
public class Homework01 {
    static class Pair<A, B> {
        A first; B second;
        Pair(A a, B b) { this.first = a; this.second = b; }
        @Override public String toString() { return "(" + first + ", " + second + ")"; }
    }

    public static void main(String[] args) {
        Pair<String, Integer> p = new Pair<>("Jisoo", 21);
        System.out.println(p);
    }
}

answer/Homework02.java

java
import java.util.List;

/** Sum of numbers using bounded wildcard. */
public class Homework02 {
    static double sumOf(List<? extends Number> list) {
        double s = 0;
        for (Number n : list) s += n.doubleValue();
        return s;
    }

    public static void main(String[] args) {
        System.out.println("ints=" + sumOf(List.of(1, 2, 3)));
        System.out.println("doubles=" + sumOf(List.of(1.5, 3.0)));
    }
}

Try It Yourself

bash
cd 03_collections/13_generics/src
javac BoxDemo.java
java BoxDemo

Next Lecture

[14_Stream](../14_슀트림_API/) β€” declarative collection operations.

Example code / lecture materials

All lecture materials and example code are openly available on GitHub.

View on GitHub β†—