Generic再考 その2
この前に書いたGenericを使ったコードでは、分からない点がつあります。
public class Variant {
public Variant() {
Foo<? super MiddleType> foo1_1 = new SubFoo<MiddleType>();
Foo<? super MiddleType> foo1_2 = new SubFoo<SuperType>();
Foo<? extends MiddleType> foo2_1 = new SubFoo<MiddleType>();
Foo<? extends MiddleType> foo2_2 = new SubFoo<SubType>();
foo1_1.bar(new MiddleType());
foo1_1.bar(new SuperType()); // <- Compile Error
foo1_2.bar(new MiddleType());
foo1_2.bar(new SuperType()); // <- Compile Error
foo2_1.bar(new MiddleType()); // <- Compile Error
foo2_1.bar(new SubType()); // <- Compile Error
foo2_2.bar(new MiddleType()); // <- Compile Error
foo2_2.bar(new SubType()); // <- Compile Error
}
}
class Foo<T> {
void bar(T m) {
System.out.println("Foo is called");
}
}
class SubFoo<T> extends Foo<T> {
@Override
void bar(T m) {
System.out.println("SubFoo is called");
}
}
class MiddleType extends SuperType {
}
class SuperType {
}
class SubType extends MiddleType {
}
上記のようなコードだと、コメントで示したようにbarメソッドを呼び出すほとんどの所でコンパイルエラーになります。
bar(capture#81 of ? extends MiddleType) in Foo<capture#81 of ? extends MiddleType> cannot be applied to (MiddleType)この辺りはwildcard captureと言うキーワードがからんでいるようです。
barメソッドをgenericメソッドにすると、コンパイルエラーは解消されます。
<T> void bar(T m)クラスファイルを逆コンパイルしても、genericメソッドの導入前後で変わりがないんですよね。
型推論ってどういうメカニズムなんだろう。。。。
分からない点は以下の2点。
- 最初の段階のbarメソッド呼び出しでコンパイルエラーが出るものと出ないものがあった。
- gnericメソッドを導入した時点で何が起きているのか。
コンパイラの気持ちになって、じっくり考えて見ます。