Generics

Let’s dive into Generics, one of the most important and sometimes misunderstood features in Java.

Generics bring type safety, code reusability, and readability to Java β€” especially useful when dealing with collections, APIs, or building frameworks.


🧬 Java Generics – The Power of Type Safety


πŸ” What Are Generics?

Generics allow you to write code that works with any type, while maintaining compile-time type checking.

Instead of writing different versions of the same code for different types (like Integer, String, etc.), you write it once using type parameters like <T>.


βœ… Why Use Generics?

FeatureBenefit
Type safetyErrors caught at compile-time (no ClassCastException at runtime)
Code reusabilityOne method or class for multiple data types
Eliminate castingAvoid manual type conversion
Clean, maintainableImproves API and code readability

βœ… Real-world: Generics are used everywhere β€” in Collections, Streams, custom libraries, and frameworks like Spring and Hibernate.


πŸ“¦ Without vs With Generics

πŸ”΄ Without Generics (Old style):

List list = new ArrayList();
list.add("hello");
String str = (String) list.get(0); // manual cast

βœ… With Generics:

List<String> list = new ArrayList<>();
list.add("hello");
String str = list.get(0); // no cast needed βœ…

🎯 Generic Class Example

public class Box<T> {
    private T value;

    public void set(T value) { this.value = value; }
    public T get() { return value; }

    public static void main(String[] args) {
        Box<Integer> intBox = new Box<>();
        intBox.set(100);

        Box<String> strBox = new Box<>();
        strBox.set("Java");

        System.out.println(intBox.get()); // 100
        System.out.println(strBox.get()); // Java
    }
}

🎯 Generic Method Example

public class Printer {
    public static <T> void print(T data) {
        System.out.println(data);
    }

    public static void main(String[] args) {
        print("Hello");
        print(123);
        print(3.14);
    }
}
  • <T> before return type tells the compiler it’s a generic method.

πŸ“Œ Multiple Type Parameters

public class Pair<K, V> {
    private K key;
    private V value;

    public Pair(K key, V value) {
        this.key = key; this.value = value;
    }

    public K getKey() { return key; }
    public V getValue() { return value; }
}

πŸ“Œ Bounded Type Parameters

Use extends to restrict what type can be used with a generic.

public class MathUtils<T extends Number> {
    public double doubleValue(T num) {
        return num.doubleValue();
    }
}

Now you can only use Integer, Double, Float, etc.


πŸ“Œ Wildcards (?, extends, super)

SyntaxMeaning
<?>Unknown type
<? extends Number>Accepts Number or any subclass
<? super Integer>Accepts Integer or any superclass

πŸ”§ Example:

public static void printList(List<?> list) {
    for (Object item : list) {
        System.out.println(item);
    }
}

Use wildcards when you’re reading, not modifying the list.


🧠 Common Interview Q: Why no List<T>[]?

Java doesn’t allow generic array creation due to type erasure. You can’t do:

List<String>[] list = new ArrayList<String>[10]; // Compile error ❌

But you can use:

List<?>[] list = new ArrayList<?>[10]; // Warning suppressed

🧠 Summary Table

FeaturePurpose
<T>Declare generic type
<T extends Number>Restrict to specific types
List<?>Accept any list
<? extends T>For reading from structure
<? super T>For writing to structure
Generics + CollectionsType-safe data handling

🏠 Homework for Students

Task 1: Create a generic class Container<T> with methods:

  • void add(T item)
  • T get(int index)

Test it with both Integer and String types.


Task 2: Write a method:

<T extends Comparable<T>> T findMax(List<T> list)

Which returns the largest element in the list.


Task 3: Use wildcard:

Write a method that takes a List<?> and prints all elements, regardless of type.


Task 4: Create a generic Pair<K, V> class and print key-value pairs of type:

  • String, Integer
  • String, String

Would you like to move into Lambda Expressions & Streams next, which build beautifully on generics and are core to modern Java (Java 8+)?