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
- 01Write a generic first-or-default helper.
- 02Call it with strings and integers; compile with -Xlint:unchecked.
- 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.
- 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.
- 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.
- 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>?
BUILD IT YOURSELF
Write a generic first-or-default helper.
- 1.Write a generic first-or-default helper.
- 2.Call it with strings and integers; compile with -Xlint:unchecked.
- 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.