1.1 Deep Dive: Generics, Invariance & Type Bounds
Module 1: Generics & Type Safety in Depth

1.1 Deep Dive: Generics, Invariance & Type Bounds

Estimated reading & practice time: ~20 minutes

Learning Objectives

• Create custom generic classes and methods with `<T>`. • Implement upper bounds (`<T extends Comparable<T>>`). • Understand why Java generics are invariant.

Mental Model & Analogy

Think of a generic class like a universal shipping container. Without labels (raw types), you could throw fish, laptops, and chemical paint into the same box, causing disaster when unpacked. Generics are tamper-proof customs seals (`Container<Laptop>`) ensuring only declared types enter the box.

Core Concept Breakdown

Generics enforce compile-time type safety. Prior to Java 5, collections stored raw `Object` references, requiring manual casting that frequently crashed with `ClassCastException` at runtime. Key Concepts: 1. **Type Invariance**: In Java, although `Integer` is a subtype of `Number`, `List<Integer>` is NOT a subtype of `List<Number>`! If it were, you could add a `Double` into a `List<Integer>` reference, breaking type safety. 2. **Type Bounds (`<T extends Comparable<T>>`)**: Restricts generic parameters to types implementing specific interfaces or extending base classes. 3. **Type Erasure**: The JVM strips generic metadata at runtime and replaces `T` with its upper bound (`Object` or the bounded type) to maintain backwards compatibility.

Architecture Diagram

Compile-Time Check List<String> box = new ArrayList<>() box.add(100) -> Compiler Error! Runtime Bytecode (Type Erasure) List box = new ArrayList() Automatic synthetic cast (String) box.get(0)

Code Example

JAVA Example
class DataStore<T extends Comparable<T>> {
    private T item;

    public void set(T item) {
        this.item = item;
    }

    public T get() {
        return item;
    }

    public boolean isGreaterThan(T other) {
        return item.compareTo(other) > 0;
    }
}

public class GenericsDemo {
    public static void main(String[] args) {
        DataStore<Integer> scoreStore = new DataStore<>();
        scoreStore.set(95);
        System.out.println("Score 95 > 80? " + scoreStore.isGreaterThan(80));

        DataStore<String> wordStore = new DataStore<>();
        wordStore.set("TBLearn");
        System.out.println("Stored: " + wordStore.get());
    }
}

Line-by-Line Walkthrough

• `<T extends Comparable<T>>` establishes a bound: whatever type fills `T` must implement `Comparable`. • The compiler guarantees compile-time safety without runtime casting errors.
Expected Console Output
Score 95 > 80? true
Stored: TBLearn

Common Pitfalls & Debugging

• Trying to instantiate generic types directly: `new T()` is illegal because `T` is erased to Object at runtime. • Using primitive types directly like `DataStore<int>` instead of wrapper `DataStore<Integer>`.

Try It Yourself — Java Sandbox

Live Execution

Create a generic class `Pair<K, V>` holding two distinct generic types with getter methods for `first` and `second`.

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.