Java - Generics and Type Erasure in Java
1. What are Generics?
Generics allow you to define classes, interfaces, and methods with a placeholder for the data type. This enables compile-time type safety and eliminates explicit type casting.
Without generics:
List list = new ArrayList();
list.add("Hello");
String s = (String) list.get(0); // explicit casting required
With generics:
List<String> list = new ArrayList<>();
list.add("Hello");
String s = list.get(0); // no casting needed
Here, String is the type parameter.
2. Generic Class
class Box<T> {
private T value;
public void set(T value) {
this.value = value;
}
public T get() {
return value;
}
}
Usage:
Box<Integer> box = new Box<>();
box.set(10);
Integer num = box.get();
T can be replaced with any reference type.
3. Generic Methods
Generics can also be used in methods:
public static <T> void printArray(T[] array) {
for (T element : array) {
System.out.println(element);
}
}
<T> before return type declares the type parameter.
4. Bounded Type Parameters
You can restrict the type:
class Calculator<T extends Number> {
T num;
}
Now T must be a subclass of Number (Integer, Double, etc.).
Multiple bounds:
<T extends Number & Comparable<T>>
5. Wildcards
Used mainly in collections.
Unbounded:
List<?> list;
Upper bounded:
List<? extends Number>
Lower bounded:
List<? super Integer>
Rule:
-
extends→ read-only (producer) -
super→ write-safe (consumer)
This follows the PECS principle:
Producer Extends, Consumer Super.
6. Type Erasure
Java generics are implemented using type erasure.
At runtime, generic type information is removed. The compiler replaces type parameters with:
-
Their bound type (if bounded)
-
Object(if unbounded)
Example:
List<String> list = new ArrayList<>();
After compilation (conceptually):
List list = new ArrayList();
Because of type erasure:
-
You cannot create generic arrays:
new T[10]; // not allowed -
You cannot use primitives as type parameters:
List<int> // not allowed List<Integer> // correct -
Runtime type checking does not know generic types:
list instanceof List<String> // not allowed
7. Why Type Erasure?
Java maintains backward compatibility with older versions (before Java 5). The JVM does not store generic type information.
8. Advantages of Generics
-
Compile-time type safety
-
No need for casting
-
Code reusability
-
Better readability
-
Fewer runtime errors
9. Common Interview Questions
-
Difference between
List<?>andList<Object> -
What is PECS rule?
-
Why can’t we use primitives in generics?
-
What is type erasure?
-
Why can’t we create generic arrays?
In short:
Generics improve type safety and reusability at compile time, while type erasure removes generic information at runtime to maintain backward compatibility.