1.2 Wildcards & The PECS Rule in Practice
Module 1: Generics & Type Safety in Depth

1.2 Wildcards & The PECS Rule in Practice

Estimated reading & practice time: ~20 minutes

Learning Objectives

• Apply the PECS rule (Producer Extends, Consumer Super). • Write flexible API methods that accept collections of subtypes. • Understand when and why lower bounds (`? super`) are essential.

Mental Model & Analogy

PECS is like a kitchen pantry: If a shelf produces ingredients for your recipe, any shelf with food or its gourmet subtypes will do (`? extends Food`). But if you are putting washed dishes into a cabinet, the cabinet must be capable of holding dishes or general household items (`? super Dish`).

Core Concept Breakdown

Joshua Bloch summarized wildcards in Effective Java: **PECS stands for Producer Extends, Consumer Super**. 1. **Producer (`? extends T`)**: If a parameterized type represents a producer that only gives you values, use `? extends T`. You can read items as `T`, but you cannot add items into the collection because the compiler cannot guarantee the exact subtype. 2. **Consumer (`? super T`)**: If a parameterized type represents a consumer that takes values you provide, use `? super T`. You can safely write items of type `T` into it. 3. **Unbounded (`?`)**: Use when only reading `Object` properties like size or clear.

Architecture Diagram

Producer Extends (? extends Number) READ ONLY - Safe to read as Number list.add(10) is FORBIDDEN by compiler Consumer Super (? super Integer) WRITE SAFE - Safe to add Integer Reads return Object only

Code Example

JAVA Example
import java.util.*;

public class PecsDemo {
    // Producer: reads items from numbers, calculates sum
    public static double sumOfNumbers(List<? extends Number> list) {
        double sum = 0.0;
        for (Number n : list) {
            sum += n.doubleValue();
        }
        return sum;
    }

    public static void main(String[] args) {
        List<Integer> ints = Arrays.asList(10, 20, 30);
        List<Double> doubles = Arrays.asList(1.5, 2.5, 3.5);

        System.out.println("Integer Sum: " + sumOfNumbers(ints));
        System.out.println("Double Sum:  " + sumOfNumbers(doubles));
    }
}

Line-by-Line Walkthrough

• `List<? extends Number>` accepts both `List<Integer>` and `List<Double>`. • Inside the loop, elements are read safely as `Number` without runtime errors.
Expected Console Output
Integer Sum: 60.0
Double Sum:  7.5

Common Pitfalls & Debugging

• Calling `list.add(...)` on a `List<? extends Number>` parameter: this causes a compile-time error because Java does not know if the actual list is an `ArrayList<Double>` or `ArrayList<Long>`.

Try It Yourself — Java Sandbox

Live Execution

Write a method `copyList(List<? extends T> src, List<? super T> dest)` that copies all elements from `src` into `dest`.

Solution.java
Edit the code and click Run Code to verify output directly inside TBLearn.
1
Terminal Output
Click "Run Code" or press Ctrl+Enter to execute.
Knowledge Checkpoint • Earn +40 Credits

Test Yourself Before Moving Forward

Short, practical questions tied directly to this section. Passing awards Credits toward course discounts and interview packs.

Module 1 Checkpoint: Collections & Generics

Verify `ArrayList` vs `HashMap`, `equals`/`hashCode` contracts, and generic type safety.