2318. Java Core - Generics Type ErasureType Erasure
Learn what is Type Erasure and how generics works.
1. Type Erasure
Generics are used for tighter type checks at compile time and to provide a generic programming. To implement generic behavior, java compiler apply type erasure. Type erasure
is a process in which compiler replaces a generic parameter with actual class or bridge method. In type erasure, compiler ensures that no extra classes are created and there is no runtime overhead.
Type erasure rules:
- Replace type parameters in generic type with their
bound
if bounded type parameters are used. - Replace type parameters in generic type with
Object
if unbounded type parameters are used. - Insert type casts to preserve type safety.
- Generate bridge methods to keep polymorphism in extended generic types.
2. Erasure Examples
2.1 Bounded Types Erasure
Java Compiler replaces type parameters in generic type with their bound if bounded type parameters are used.
Example.
public class BoundedTypesErasureExample {
public static void main(String[] args) {
Box<Integer> integerBox = new Box<Integer>();
Box<Double> doubleBox = new Box<Double>();
integerBox.add(new Integer(10));
doubleBox.add(new Double(10.0));
System.out.format("Integer Value: %d\n", integerBox.get());
System.out.format("Double Value: %s\n", doubleBox.get());
}
static class Box<T extends Number> {
private T t;
public void add(T t) {
this.t = t;
}
public T get() {
return t;
}
}
}
In this case, java compiler will replace T
with Number
class and after type erasure, compiler will generate bytecode for the following code.
public class BoundedTypesErasureExample {
public static void main(String[] args) {
Box integerBox = new Box();
Box doubleBox = new Box();
integerBox.add(new Integer(10));
doubleBox.add(new Double(10.0));
System.out.format("Integer Value: %d\n", integerBox.get());
System.out.format("Double Value: %s\n", doubleBox.get());
}
static class Box {
private Number t;
public void add(Number t) {
this.t = t;
}
public Number get() {
return t;
}
}
}
2.2 Unbounded Types Erasure
Java Compiler replaces type parameters in generic type with Object if unbounded type parameters are used.
Example.
public class UnboundedTypesErasureExample {
public static void main(String[] args) {
Box<Integer> integerBox = new Box<Integer>();
Box<String> stringBox = new Box<String>();
integerBox.add(new Integer(10));
stringBox.add(new String("Hello World"));
System.out.format("Integer Value: %d\n", integerBox.get());
System.out.format("String Value: %s\n", stringBox.get());
}
static class Box<T> {
private T t;
public void add(T t) {
this.t = t;
}
public T get() {
return t;
}
}
}
In this case, java compiler will replace T
with Object
class and after type erasure, compiler will generate bytecode for the following code.
public class UnboundedTypesErasureExample {
public static void main(String[] args) {
Box integerBox = new Box();
Box stringBox = new Box();
integerBox.add(new Integer(10));
stringBox.add(new String("Hello World"));
System.out.format("Integer Value: %d\n", integerBox.get());
System.out.format("String Value: %s\n", stringBox.get());
}
static class Box {
private Object t;
public void add(Object t) {
this.t = t;
}
public Object get() {
return t;
}
}
}
2.3 Methods Erasure
Java compiler replaces type parameters in generic type with Object if unbounded type parameters are used, and with type if bound parameters are used as method parameters.
Example.
public class MethodsErasureExample {
public static void main(String[] args) {
Box<Integer> integerBox = new Box<Integer>();
Box<String> stringBox = new Box<String>();
integerBox.add(new Integer(10));
stringBox.add(new String("Hello World"));
printBox1(integerBox);
printBox2(stringBox);
}
private static <T extends Box> void printBox1(T box) {
System.out.println("Integer Value: " + box.get());
}
private static <T> void printBox2(T box) {
System.out.println("String Value: " + ((Box)box).get());
}
static class Box<T> {
private T t;
public void add(T t) {
this.t = t;
}
public T get() {
return t;
}
}
}
In this case, java compiler will replace T
with Object
class and after type erasure, compiler will generate bytecode for the following code.
public class MethodsErasureExample {
public static void main(String[] args) {
Box integerBox = new Box();
Box stringBox = new Box();
integerBox.add(new Integer(10));
stringBox.add(new String("Hello World"));
printBox1(integerBox);
printBox2(stringBox);
}
//Bounded Types Erasure
private static void printBox1(Box box) {
System.out.println("Integer Value: " + box.get());
}
//Unbounded Types Erasure
private static void printBox2(Object box) {
System.out.println("String Value: " + ((Box)box).get());
}
static class Box {
private Object t;
public void add(Object t) {
this.t = t;
}
public Object get() {
return t;
}
}
}