Discuss Java Generics.

Generics is a feature in Java that enables classes, interfaces, and methods to work with different data types while maintaining compile-time type safety. It allows developers to write reusable code without sacrificing type checking, reducing the risk of runtime errors such as ClassCastException.

Key Points: • Generics provide strong type safety at compile time. • They eliminate the need for explicit type casting in many situations. • Generics improve code reusability and readability. • They help detect type-related errors before the application runs. • Collections such as List, Set, Map, and Queue heavily use Generics.

Why Were Generics Introduced?

Before Java 5, collections stored objects as Object references.

Example:

List list = new ArrayList();

list.add("Java");

String value = (String) list.get(0);

Problems:

• Manual type casting required. • Risk of ClassCastException at runtime. • Reduced type safety.

Generics solve these issues by specifying the expected data type.

Example:

List<String> list = new ArrayList<>();

list.add("Java");

String value = list.get(0);

No type casting is required.

Benefits of Generics

1. Type Safety

The compiler verifies data types during compilation.

Example:

List<String> names =
        new ArrayList<>();

names.add("John");

names.add(100);

Compilation Error

This prevents invalid data from being added.

2. Eliminates Explicit Casting

Without Generics:

String name =
        (String) list.get(0);

With Generics:

String name =
        list.get(0);

3. Code Reusability

A single class or method can work with multiple data types.

Example:

Box<Integer>

Box<String>

Box<Employee>

Generic Class Example

Code Example:

class Box<T> {

    private T value;

    public void setValue(T value) {

        this.value = value;
    }

    public T getValue() {

        return value;
    }
}

public class Demo {

    public static void main(String[] args) {

        Box<String> box =
                new Box<>();

        box.setValue("Java");

        System.out.println(
                box.getValue());
    }
}

Output:

Java

Here:

T represents a type parameter.

Generic Method Example

Code Example:

public class Utility {

    public static <T> void print(T value) {

        System.out.println(value);
    }
}

Usage:

Utility.print("Java");

Utility.print(100);

Utility.print(true);

The same method works for different types.

Generic Interfaces

Interfaces can also use Generics.

Example:

interface Repository<T> {

    void save(T entity);

    T findById(int id);
}

This allows implementation for different entity types.

Bounded Generics

Sometimes we want to restrict the allowed types.

Example:

class Calculator<T extends Number> {

}

Allowed:

Integer

Double

Float

Not Allowed:

String

This ensures only numeric types are accepted.

Wildcards in Generics

Java provides wildcards using ?.

Example:

List<?> list;

Meaning:

The list can contain elements of any type.

Common Wildcards:

<?> Any type

<? extends T> T or subclass

<? super T> T or superclass

Type Erasure

Java implements Generics using Type Erasure.

Meaning:

Generic type information exists during compilation but is removed at runtime.

Example:

List<String>

List<Integer>

At runtime both become:

List

This ensures backward compatibility with older Java versions.

Common Uses of Generics

• Collection Framework • Repository pattern • Utility classes • Framework development • API design

Example: Consider an application that manages employees, products, and customers.

Without Generics:

Separate classes may be needed for each type.

With Generics:

A single reusable class can handle all entity types safely.

Advantages of Generics

• Compile-time type checking • Better code reusability • Improved readability • Reduced casting • Fewer runtime errors

Limitations of Generics

• Cannot use primitive types directly

Invalid:

List<int>

Valid:

List<Integer>

• Type information is removed at runtime due to Type Erasure. • Cannot create generic arrays directly.

Interview Tip: A concise interview answer is:

"Generics allow classes, interfaces, and methods to operate on different data types while maintaining compile-time type safety. They reduce code duplication, eliminate explicit type casting, and help prevent ClassCastException. Generics are extensively used in the Java Collection Framework to create reusable and type-safe code."