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?