Type erasure only seems to occur when instantiating a generic type, but if you extend a generic type and provide a concrete type in place of T
, the type is available at runtime. It seems to be the only time that the type isn't erased.
In the following example, String
will be erased:
List<String> text = new ArrayList<>();
In the following example, as the implementation is still generic, any usage of it will erase whatever is in place of T
.
public final class ArrayList<T> implements List<T> { ... }
But, the moment the implementation is no longer generic, where T
has been replaced by a concrete type in the inheritance chain, it's discoverable via reflection.
public final class IntegerList implements List<Integer> { ... }
Why doesn't the type get erased when implemented via inheritance?
But, the moment the implementation is no longer generic ...
That's the answer. Type erasure occurs for generic types. The subclass IntegerList
is not generic. Non-generic types are reifiable, which means that the types are available at runtime.
From the Java Language Specification, 4.7: Reifiable Types:
4.7 Reifiable Types
Because some type information is erased during compilation, not all types are available at run time. Types that are completely available at run time are known as reifiable types.
A type is reifiable if and only if one of the following holds:
• It refers to a non-generic class or interface type declaration.
...