The Java Language Specification mandates that this method is treated in a special way by the compiler:
The method getClass
returns the Class
object that represents the class of the object.
A Class
object exists for each reference type. It can be used, for example, to discover the fully qualified name of a class, its members, its immediate superclass, and any interfaces that it implements.
The type of a method invocation expression of getClass is Class<? extends |T|>
where T
is the class or interface searched (§15.12.1) for getClass.
So the return type of getClass is the static (compile-time) type of the expression getClass()
is invoked on. For instance:
String s = "";
Object o = s;
Class<? extends String> sc = s.getClass(); // ok
Class<? extends Object> oc = o.getClass(); // ok
oc = sc; // ok
sc = o.getClass(); // not ok
sc = oc; // not ok
The notation |X|
is defined in spec as follows:
Type erasure is a mapping from types (possibly including parameterized types and type variables) to types (that are never parameterized types or type variables). We write |T|
for the erasure of type T
. The erasure mapping is defined as follows:
The erasure of a parameterized type (§4.5) G<T1,...,Tn>
is |G|
.
The erasure of a nested type T.C
is |T|.C
.
The erasure of an array type T[]
is |T|[]
.
The erasure of a type variable (§4.4) is the erasure of its leftmost bound.
The erasure of every other type is the type itself.
For instance, if we have:
List<String> list = ...;
the expression list.getClass()
is of type Class<? extends List>
rather than Class<? extends List<String>>
.