Chapter 19: Generics

Generics let you write classes, interfaces, and methods that can work with any data type — while still keeping strong type checking at compile time.

Imagine we’re sitting together in a quiet Mumbai café — it’s evening, the city is glowing outside, and I’m going to explain generics like I’m teaching my younger brother who just discovered why ArrayList<String> is so much better than the old ArrayList without types.

We’ll go super slowly, with real-life analogies, complete runnable programs, step-by-step breakdowns, tables, common mistakes with fixes, and tons of examples you can copy-paste and run right now.

Let’s dive in!

1. Why Generics? (The Big Problem They Solve)

Before generics (pre-Java 5), collections were not type-safe:

Java

Problems:

  • No compile-time type checking → bugs only appear at runtime
  • Every get() needs manual casting → ugly and error-prone
  • Mixing types accidentally → dangerous

Generics fix this:

Java

2. Generic Classes

A generic class uses a type parameter (usually T, E, K, V…) to represent any type.

Syntax:

Java

Usage:

Java

Real-life analogy: Box<T> is like a gift box.

  • You can put any gift inside (String, Integer, Student…)
  • But when you open it, you know exactly what type is inside → no surprise!

3. Generic Methods

A generic method can have its own type parameter — independent of the class.

Syntax:

Java

Usage:

Java

4. Bounded Types (Restrict the Type Parameter)

You can limit the type parameter to a specific class or interface.

Syntax:

Java

Example: Generic class with bounded type

Java

Usage:

Java

5. Wildcards (The ? Magic)

Wildcards let you work with unknown types safely.

Wildcard Type Syntax Meaning / Use Case
Unbounded wildcard ? Any type — read-only (safe for getting elements)
Upper bounded wildcard ? extends Type Any type that is Type or subclass of Type — read-only
Lower bounded wildcard ? super Type Any type that is Type or superclass of Type — write-only (add elements)

Example: Upper bounded wildcard

Java

Usage:

Java

Example: Lower bounded wildcard (PECS rule)

Java

PECS Rule (very important!):

  • Producer Extends → use ? extends when you read from collection
  • Consumer Super → use ? super when you write to collection

6. Quick Recap Table (Your Cheat Sheet)

Concept Syntax / Example Purpose / Benefit
Generic Class class Box<T> Type-safe reusable container
Generic Method <T> void print(T item) Flexible methods for any type
Bounded Type <T extends Number> Restrict to specific types/interfaces
Unbounded Wildcard List<?> Accept any List (read-only)
Upper Bounded Wildcard List<? extends Animal> Read from list safely
Lower Bounded Wildcard List<? super Dog> Write to list safely

7. Common Mistakes & Fixes

Mistake Problem Fix
Using raw types (List instead of List<String>) Lose type safety — compiler warnings Always use generics: List<String>
List<?> and trying to add Compile error — unknown type Use List<? super T> if you want to write
Creating new T() inside generic class Compile error — T might not have constructor Use factory pattern or pass instance
Forgetting <> after new Raw type warning Use diamond operator: new ArrayList<>()
Mixing generics with arrays Arrays don’t support generics well Prefer ArrayList<T> over T[]

8. Homework for You (Practice to Master!)

  1. Basic: Create generic class Pair<K, V> with two fields (key, value). Use it to store name-age pairs.
  2. Medium: Write generic method swap(T[] array, int i, int j) that swaps two elements.
  3. Advanced: Create generic method max(T[] array) that finds maximum element (T must implement Comparable<T>).
  4. Fun: Create generic class Stack<T> with push/pop methods using ArrayList<T>.
  5. Challenge: Fix this code — why does it fail and how to make it type-safe?
    Java

You’re doing amazing! Generics are the secret sauce that makes Java collections safe, readable, and powerful — now you can write professional, modern Java code.

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *