Java Generics

Type-safe programming with parameterized types

🎯 What are Generics?

Generics enable types to be parameters when defining classes, interfaces, and methods. They provide compile-time type safety and eliminate the need for casting.


// Generic ArrayList - type safe
ArrayList<String> names = new ArrayList<>();
names.add("John");
String name = names.get(0); // No casting needed
                                    

Output:

names: ["John"]

name: "John" (String type guaranteed)

Generic Features

📋

Generic Classes

Classes with type parameters

class Box<T> {
    private T item;
}
⚙️

Generic Methods

Methods with type parameters

public <T> void swap(T[] array, int i, int j)
🔒

Bounded Types

Restrict generic types

class NumberBox<T extends Number>
🌟

Wildcards

Flexible type matching

List<? extends Number> numbers

🔹 Generic Class Example

Creating a generic class that can work with any type:

// Generic class definition
class Container<T> {
    private T item;
    
    public void setItem(T item) {
        this.item = item;
    }
    
    public T getItem() {
        return item;
    }
}

// Using the generic class
Container<String> stringBox = new Container<>();
stringBox.setItem("Hello");
String message = stringBox.getItem();

Container<Integer> intBox = new Container<>();
intBox.setItem(42);
Integer number = intBox.getItem();

Output:

message: "Hello"

number: 42

🔹 Generic Methods

Methods that can work with different types:

public class GenericMethods {
    
    // Generic method to swap array elements
    public static <T> void swap(T[] array, int i, int j) {
        T temp = array[i];
        array[i] = array[j];
        array[j] = temp;
    }
    
    // Generic method to find maximum
    public static <T extends Comparable<T>> T findMax(T[] array) {
        T max = array[0];
        for (T item : array) {
            if (item.compareTo(max) > 0) {
                max = item;
            }
        }
        return max;
    }
}

// Usage
String[] words = {"apple", "banana", "cherry"};
GenericMethods.swap(words, 0, 2);
String maxWord = GenericMethods.findMax(words);

Output:

After swap: ["cherry", "banana", "apple"]

maxWord: "cherry"

🔹 Wildcards in Generics

Using wildcards for flexible generic types:

import java.util.*;

public class WildcardExample {
    
    // Upper bounded wildcard
    public static double sumNumbers(List<? extends Number> numbers) {
        double sum = 0.0;
        for (Number num : numbers) {
            sum += num.doubleValue();
        }
        return sum;
    }
    
    // Lower bounded wildcard
    public static void addNumbers(List<? super Integer> numbers) {
        numbers.add(1);
        numbers.add(2);
        numbers.add(3);
    }
}

// Usage
List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5);
List<Double> doubles = Arrays.asList(1.1, 2.2, 3.3);

double intSum = WildcardExample.sumNumbers(integers);
double doubleSum = WildcardExample.sumNumbers(doubles);

Output:

intSum: 15.0

doubleSum: 6.6

🧠 Test Your Knowledge

What is the main benefit of using generics in Java?