What is Type Erasure?
The process of imposing type constraints at compile-time and discard the element type information at runtime.
In the other words, the compiler replaces a generic parameter with the actual class or bridge method. moreover, the compiler ensures that no extra classes are created and there is no runtime overhead.
In fact, type erasure ensures your code to be compatible with older versions of java which may not contain generics at all.
Flowers flower = sample.emptyBucket();
the compiler will turn the above code in a casted way.
Flowers flower = (Object) sample.emptyBucket();
Type Erasure Pros.
- Backward compatibility in Two-way
- Much easier to implement
- No byte code or Virtual Machine needs to be changed
- JIT compiler spent less time and less RAM is used to store the generated code due to generating from one version for all generic instances.
- Better in Performance due to smaller number of objects in the heap memory.
Types of type erasure.
- Class level Type erasure
- Method level type erasure
Here the compiler ignores the type parameters on the class and replaces them with the first bound.
Sometimes the type parameter can be bounded.
The bound type parameter is replaced by the compiler with the first Bound class.
For easy understanding, method-level erasure can be stated as follows.
- If unbound, the method’s parameter is converted to its parent type Object while it is not being stored.
- If bound, the method’s parameter is converted to its first bound class.
Let’s elaborate on the method level type erasure by an implementation.
The below example of an Element counter shows the first case, unbound.
Moving on, the following sample method declarations are to elaborate the bounded declaration.
Let’s familiarize with Synthetic methods and classes…
Java compiler introduces these synthetic Classes, methods, fields, and any other similar construct which are not visible directly in the source code.
These are only for runtime’s internal purposes. As a programmer, you might have encountered bugs definitely. you might have knowingly or unknowingly gone through the stack trace where you got some helpful synthetic output.
In the process of type erasure compiler sometimes create synthetic methods when there are similar methods. in fact, this is mainly because to distinguish one method from the other.
For instance, let's try out implementations to be handy with the concepts.
Before type erasure.
After type erasure.
The last line throws an exception. since we have put an item which is a String type object to the SampleChild where the putItem(Object) inherited from the sample<Integer> type. Thus, the last line throws a ClastCastException.
The ambiguity of method signatures in extended parameterized class or implemented parameterized interface by a class or interface create these Bridge methods. In fact, these are synthetic methods to solve the edge case that we discussed in the above section and also for covariant return types.
The compiler performs polymorphism of generic types after type erasure by ensuring no conflicts between the following methods of two classes.
SampleChild class — —> putItem(Integer) method
Sample Class — — — — >putItem(Object) method