假设我有以下类:
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();
}
}
但是,这是一个编译错误:
invalid inferred types for S; inferred type does not conform to declared bound(s) inferred: MySImpl bound(s): 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)
在第二个示例中都工作正常。
但是:这是 OpenJDK 1.6 编译器中的错误还是 Java 语言规范中的歧义?
最佳答案
在第二个示例中,参数类型没有以任何方式提及 S。编译器告诉您它因此无法推断出它。
详细说明。在第一个示例中,您要求 Class<? extends MyT<S, T>>
.在 test()
, 你给它一个 Class<MyTImpl>
.当编译器检查边界时,它匹配 MyT<S, T>
反对MyTImpl
并发现 MyTImpl
工具 MyT<MySImpl, MyTImpl>
, 所以它可以推断出 MySImpl
对于 S
和 MyTImpl
对于 T
只需将这两件事放在一起。
然后它检查 S
上的约束和 T
对于 MySImpl
和 MyTImpl
, 成功。
在第二个例子中,你要求一个 Class<T>
.编译器看到 Class<MyTImpl>
, 推断 MyTImpl
对于 T
, 完成了。无法推断 S
, 它出错了。
T
的约束检查, 可以提供什么信息S
是,不会发生。
关于java - 为什么泛型类型的推断在这里不起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17093011/