Loading published curriculum…

04 · Java language in depth / LESSON 12 OF 102

Generics, bounds, and wildcards

Generics move type mistakes from runtime casts into compiler checks.

Before this lesson: Inheritance, overriding, and polymorphism

Understand the topic

List<Integer> is not a subtype of List<Number>; otherwise callers could insert a Double into an integer list. Use ? extends Number when a collection produces numbers and ? super Integer when it consumes integers. A wildcard is not permission to insert arbitrary objects.

Type erasure means most generic type parameters are unavailable at runtime. Avoid raw List and unchecked casts. Generic methods introduce their own type parameter before the return type and can constrain it with extends.

EXAMPLE · JAVA

Main.java

import java.util.List;
public class Main {
  static double total(List<? extends Number> values) {
    return values.stream().mapToDouble(Number::doubleValue).sum();
  }
  public static void main(String[] args) {
    System.out.println(total(List.of(2, 3)));
  }
}

What to expect

Prints 5.0; total also accepts List<Double> without unsafe casts.

YOUR TURN

Put it into practice

  1. 01Write a generic first-or-default helper.
  2. 02Call it with strings and integers; compile with -Xlint:unchecked.
  3. 03Verify: No raw types or unchecked warnings remain and an empty list returns the supplied default.

Pass a quiz or complete a lab to check today’s streak. Each lesson counts once per day, including when you review it later.

UNDER THE HOOD

Build the mental model

Generics move type mistakes from runtime casts into compiler checks.

  1. 01List<Integer> is not a subtype of List<Number>; otherwise callers could insert a Double into an integer list. Use ? extends Number when a collection produces numbers and ? super Integer when it consumes integers. A wildcard is not permission to insert arbitrary objects.
  2. 02Type erasure means most generic type parameters are unavailable at runtime. Avoid raw List and unchecked casts. Generic methods introduce their own type parameter before the return type and can constrain it with extends.
  3. 03Trace the example: Prints 5.0; total also accepts List<Double> without unsafe casts.

A mistake worth avoiding

Adding an Integer to List<? extends Number> fails to compile.

DEBUGGING ROOM

Something broke. Where do you look?

Adding an Integer to List<? extends Number> fails to compile.

Before revealing the diagnosis, write down your first investigation step.

CHECK YOUR UNDERSTANDING

Can List<Integer> safely be assigned to List<Number>?

Choose one answer

BUILD IT YOURSELF

Write a generic first-or-default helper.

  1. 1.Write a generic first-or-default helper.
  2. 2.Call it with strings and integers; compile with -Xlint:unchecked.
  3. 3.Reproduce this failure, then repair it: Adding an Integer to List<? extends Number> fails to compile.

Acceptance checklist

Lab completion is your self-report. Knowledge checks do not certify project quality.

RETRIEVE IT FROM MEMORY

Can List<Integer> safely be assigned to List<Number>?

Revisit this lesson in three days after a successful check or lab.

Ready for the next step?

No raw types or unchecked warnings remain and an empty list returns the supplied default.

Reading is separate from passing a knowledge check or completing a lab.

Go deeper · official references