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);
}