The following Java method fails to compile:
void foo(T t)
{
Class extends T> klass = t.getClass();
}
Error
It is kind of silly. It would have been better, for most use cases, if x.getClass() returns Class extends X>, instead of the erased Class extends |X|>.
The erasure is the cause of loss of information, making your code, apparently safe, fail to compile. t.getClass() returns Class extends |T|>, and |T| = Number, so it returns Class extends Number>.
The erasure (mandated by the language spec) is to maintain theoretical correctness. For example
List x = ...;
Class c1 = x.getClass(); // ok
Class> c2 = x.getClass(); // error
Although c2 seems very reasonable, in Java, there is really no such class for List. There is only the class for List. So allowing c2 would be, theoretically incorrect.
This formality created lots of problem in real world usages, where programmers can reason that Class extends X> is safe for their purposes, but have to cope with the erased version.
You can simply define your own getClass that returns the un-erased type
static public Class extends X> getFullClass(X x)
return (Class extends X>)(Class) x.getClass() ;
void foo(T t)
{
Class extends T> klass = getFullClass(t);
}