java - 为什么泛型类型的推断在这里不起作用?

标签 java generics

假设我有以下类:

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对于 SMyTImpl对于 T只需将这两件事放在一起。

然后它检查 S 上的约束和 T对于 MySImplMyTImpl , 成功。

在第二个例子中,你要求一个 Class<T> .编译器看到 Class<MyTImpl> , 推断 MyTImpl对于 T , 完成了。无法推断 S , 它出错了。

T 的约束检查, 可以提供什么信息S是,不会发生。

关于java - 为什么泛型类型的推断在这里不起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17093011/

相关文章:

java - 在 Osgi 中以编程方式注册 ServletContainer

java - 考虑使用Netbeans作为JAVA的IDE

java - var 无法解析为类型 - java-10

java - 通过 BeanFactory.getBean(Class<T>) 检索通用 bean

java - 在 Java 中使用枚举来专门化模板

java - Spring Framework 仅读取英文 (en) 语言环境文件

java - 将 Epoch 值转换为 12 小时格式的时间戳

generics - Scala 泛型与 C# 的比较

c# - 在运行时指定通用委托(delegate)类型参数

c# - 一般创建正确具体类型的属性