My obviously wrong understanding of Java Generics was up to now, that Type Erasure removes all type information such that there is nothing left at all at runtime. Recently I stumbled upon a code fragment where I had to ask myself: How the hack does this work? Simplified, it presents as:
import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; public abstract class SuperClass<T> { private final Type type; protected SuperClass(){ ParameterizedType parameterizedType = (ParameterizedType) getClass().getGenericSuperclass(); type = parameterizedType.getActualTypeArguments()[0]; } public void tellMyType(){ System.out.println("Hi, my type parameter is " + type); } }
and
public class Example { public static void main(String[] args) { SuperClass sc = new SuperClass<Integer>(){}; sc.tellMyType(); } }
Executing the Main Class results in Hi, my type parameter is class java.lang.Integer
.
What we can see here is, that the type information of T is also available at runtime, which contradicts my initial understanding.
So my question is: Why does the compiler keep this? Is this required for some internal JVM behavior or is there any reasonable explanation for this effect?
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.
- Erasure is a type of alteration in document. It can be classified as chemical erasure and physical erasure.
Class Type Erasure. At the class level, the compiler discards the type parameters on the class and replaces them with its first bound, or Object if the type parameter is unbound.
Type-erasure simply means "erasing" a specific type to a more abstract type in order to do something with the abstract type (like having an array of that abstract type).
From http://www.artima.com/weblogs/viewpost.jsp?thread=208860:
It turns out that while the JVM will not track the actual type arguments for instances of a generic class, it does track the actual type arguments for subclasses of generic classes. In other words, while a new
ArrayList<String>()
is really just a newArrayList()
at runtime, if a class extendsArrayList<String>
, then the JVM knows thatString
is the actual type argument forList
's type parameter.
In your case, you are making an anonymous subclass of the parameterized type, so the type information is retained. See the article for an in-depth explanation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With