Deep Dive into Generics in Java

Basic Concepts and Syntax of Generics

Generics in Java are a powerful feature that allows us to write code with parameterized types. Generics provide compile-time type safety, making programs more robust and maintainable.

package com.example.generics;

import java.util.List;
import java.util.ArrayList;

public class GenericsExample {
    public static void main(String[] args) {
        Box<Integer> integerBox = new Box<>();
        integerBox.set(10);
        System.out.println("Integer value: " + integerBox.get());

        String[] strArray = { "Java", "C++", "Python" };
        List<String> strList = arrayToList(strArray);
        System.out.println("String list: " + strList);
    }

    public static <T> List<T> arrayToList(T[] array) {
        List<T> list = new ArrayList<>();
        for (T element : array) {
            list.add(element);
        }
        return list;
    }

    static class Box<T> {
        private T t;

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

        public T get() {
            return t;
        }
    }
}

In the code above, we demonstrate the basic usage of generics. Box<T> is a generic class, and arrayToList is a generic method. They illustrate how to define generic classes and methods, and specify concrete types when using them.

Wildcards and Bounds in Generics

Generics in Java can also be enhanced with wildcards and bounds to increase flexibility and expressiveness. The wildcard ? represents an unknown type and can be used as an upper or lower bound for generic types.

package com.example.generics;

import java.util.List;
import java.util.ArrayList;

public class WildcardExample {
    public static void main(String[] args) {
        List<Integer> integers = new ArrayList<>();
        integers.add(1);
        integers.add(2);
        integers.add(3);

        printList(integers);

        List<String> strings = new ArrayList<>();
        strings.add("Java");
        strings.add("Python");
        strings.add("C++");

        printList(strings);
    }

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

In the above code, the printList method uses the wildcard ? as the parameter type, allowing it to accept lists of any type and print their elements.

Type Erasure and Bridge Methods

Although generics in Java provide compile-time type safety, the generic type information is erased at runtime. This type erasure causes the compiler to insert bridge methods to maintain method signature consistency.

package com.example.generics;

import java.util.List;
import java.util.ArrayList;

public class TypeErasureExample {
    public static void main(String[] args) {
        List<Integer> integers = new ArrayList<>();
        integers.add(10);
        integers.add(20);

        List<String> strings = new ArrayList<>();
        strings.add("Java");
        strings.add("C++");

        System.out.println("Integer list class: " + integers.getClass());
        System.out.println("String list class: " + strings.getClass());
    }
}

In this example, although integers and strings are lists of different types, their runtime type is ArrayList. This happens because generic type information is erased at runtime.

Summary

This article provided an in-depth analysis of the basic concepts and syntax of generics in Java, including generic classes, generic methods, wildcards, and the impact of type erasure and bridge methods. Through example code, readers can better understand and utilize the powerful generics feature in Java.

Tags: java generics Type Erasure wildcards Generic Methods

Posted on Fri, 15 May 2026 18:02:43 +0000 by paperthinT