次のクラスがあるとします。
interface MyS<T extends MyT<S, T>, S extends MyS<T, S>> {
}
interface MyT<S extends MyS<T, S>, T extends MyT<S, T>> {
}
public class MySImpl implements MyS<MyTImpl, MySImpl> {
}
public class MyTImpl implements MyT<MySImpl, MyTImpl> {
}
警告なしで正常にコンパイルおよび実行される次のテストケースをビルドできます。
public class STTest {
@Test
public void test() throws Exception {
createInstance(MyTImpl.class);
}
public static<T extends MyT<S, T>, S extends MyS<T, S>> void createInstance(
final Class<? extends MyT<S, T>> beanClass) throws Exception {
final MyT<S, T> bean = beanClass.newInstance();
}
}
いいよ。しかし、これは同じ効果があると予想していました:
public class STTest {
@Test
public void test() throws Exception {
createInstance(MyTImpl.class);
}
public static<T extends MyT<S, T>, S extends MyS<T, S>> void createInstance(
final Class<T> beanClass) throws Exception {
final T bean = beanClass.newInstance();
}
}
ただし、これはコンパイル エラーです。
S の推論された型が無効です。推論された型は、推論された宣言された境界に準拠していません: MySImpl 境界: MyS
どうしてこれなの?
アップデート:
動作がコンパイラに依存していることに気付きました。コードへのコンパイルには OpenJDK 1.6 コンパイラ (javac 1.6.0_27) を使用しました。そして、それは壊れます。でも:
- OpenJDK 1.7 コンパイラ (javac 1.7.0_21) および
- Oracle 1.6 コンパイラ (javac 1.6.0_37)
2 番目の例では、どちらも正常に動作します。
しかし、これは OpenJDK 1.6 コンパイラのバグですか、それとも Java 言語仕様のあいまいさですか?