Java 6においてObject.getClass()メソッドの戻り値の型はClass<?>です。API Specification(日本語)にもそのように書かれています。しかし、実際の戻り値の型はgetClassを呼び出したオブジェクトの静的な型をTとすると、Class<? extends T>になります。そのため、次のコードは正常にコンパイルできます。
public class Sample {
public void sample() {
Sample s = new Sample();
Class<?> c1 = s.getClass(); // OK
Class<? extends Sample> c2 = s.getClass(); // OK
}
}
普通のクラスではこんなことはできません。<?>が戻り値の型に指定されたメソッドを呼び出して、<? extends Sample>が指定された変数に代入しようとしてもコンパイルエラーになるだけです。しかし、Object.getClass()メソッドはJavaコンパイラによって特殊な処理が行われるため、このようなことが可能になっています。このことについてはJava Language Specification Third Edition 4.3.2 Types, Values, and Variablesに書いてあります。
API SpecificationのObject.getClass()メソッドの説明にも同じ内容が書かれていますが、この説明では何のことかよくわかりませんでした。Java言語仕様にはこのことが明確に書かれていてわかりやすいです。
キーワード: java