Tutorials Logic, IN +91 8092939553 info@tutorialslogic.com
FAQs Support
Navigation
Home About Us Contact Us Blogs FAQs
Tutorials
All Tutorials
Services
Academic Projects Resume Writing Interview Questions Website Development
Compiler Tutorials

Java Generics

Why Generics?

Generics enable you to write classes and methods that work with any type while providing compile-time type safety. Without generics you'd need casts everywhere and could get ClassCastException at runtime.

Without GenericsWith Generics
No type checking at compile timeType errors caught at compile time
Requires explicit castingNo casting needed
Risk of ClassCastException at runtimeType-safe — no runtime surprises
Generic Class & Generic Method
// Generic class — T is a type parameter (placeholder)
class Box<T> {
    private T value;

    public Box(T value) { this.value = value; }
    public T getValue()  { return value; }
    public void setValue(T value) { this.value = value; }

    @Override
    public String toString() { return "Box[" + value + "]"; }
}

// Generic class with two type parameters
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; }

    @Override
    public String toString() { return "(" + key + ", " + value + ")"; }
}

public class Generics {

    // Generic method
    public static <T> void printArray(T[] arr) {
        for (T item : arr) System.out.print(item + " ");
        System.out.println();
    }

    public static void main(String[] args) {
        Box<Integer> intBox = new Box<>(42);
        Box<String>  strBox = new Box<>("Hello");
        System.out.println(intBox);  // Box[42]
        System.out.println(strBox);  // Box[Hello]

        Pair<String, Integer> p = new Pair<>("age", 30);
        System.out.println(p);  // (age, 30)

        Integer[] nums = {1, 2, 3, 4, 5};
        String[]  strs = {"a", "b", "c"};
        printArray(nums);  // 1 2 3 4 5
        printArray(strs);  // a b c
    }
}

Bounded Type Parameters & Wildcards

Bounded Types & Wildcards
import java.util.*;

public class BoundedGenerics {

    // Upper bound: T must be Number or a subclass
    public static <T extends Number> double sum(List<T> list) {
        double total = 0;
        for (T item : list) total += item.doubleValue();
        return total;
    }

    // Wildcard ? — unknown type
    // ? extends Number — upper bounded wildcard (read-only)
    public static void printNumbers(List<? extends Number> list) {
        for (Number n : list) System.out.print(n + " ");
        System.out.println();
    }

    // ? super Integer — lower bounded wildcard (write-friendly)
    public static void addIntegers(List<? super Integer> list) {
        list.add(1);
        list.add(2);
        list.add(3);
    }

    public static void main(String[] args) {
        List<Integer> ints    = Arrays.asList(1, 2, 3, 4, 5);
        List<Double>  doubles = Arrays.asList(1.1, 2.2, 3.3);

        System.out.println(sum(ints));     // 15.0
        System.out.println(sum(doubles));  // 6.6

        printNumbers(ints);     // 1 2 3 4 5
        printNumbers(doubles);  // 1.1 2.2 3.3

        List<Number> numbers = new ArrayList<>();
        addIntegers(numbers);
        System.out.println(numbers);  // [1, 2, 3]
    }
}

Ready to Level Up Your Skills?

Explore 500+ free tutorials across 20+ languages and frameworks.