简体   繁体   English

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

[英]Why does inferring of generic type does not work here?

Suppose I have the following classes: 假设我有以下类:

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> {
}

I can build the following testcase which compiles and runs successfully without any warning: 我可以构建以下测试用例,它可以在没有任何警告的情况下成功编译和运行:

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();
  }
}

OK, fine. 好的。 But I expected that this would have the identical effect: 但我希望这会产生相同的效果:

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();
  }
}

However, this is a compile error: 但是,这是一个编译错误:

invalid inferred types for S; S的无效推断类型; inferred type does not conform to declared bound(s) inferred: MySImpl bound(s): MyS 推断类型不符合推断的声明边界:MySImpl bound(s):MyS

Why is this? 为什么是这样?

UPDATE: 更新:

I noticed that the behaviour is compiler dependent. 我注意到该行为依赖于编译器。 I used the OpenJDK 1.6 compiler (javac 1.6.0_27) for compiling to code. 我使用OpenJDK 1.6编译器(javac 1.6.0_27)来编译代码。 And it breaks. 它打破了。 However: 然而:

  • The OpenJDK 1.7 compiler (javac 1.7.0_21) and OpenJDK 1.7编译器(javac 1.7.0_21)和
  • The Oracle 1.6 compiler (javac 1.6.0_37) Oracle 1.6编译器(javac 1.6.0_37)

both work fine on the second example. 在第二个例子中都可以正常工作。

However: Is this a bug in the OpenJDK 1.6 compiler or is this an ambiguity in the Java language specification? 但是:这是OpenJDK 1.6编译器中的错误还是Java语言规范中的歧义?

The argument type doesn't mention S in any way in the second example. 参数类型在第二个示例中没有以任何方式提及S. The compiler is telling you that it therefore can't infer it. 编译器告诉你它因此无法推断它。

To elaborate. 详细说明。 In the first example, you ask for a Class<? extends MyT<S, T>> 在第一个例子中,你要求一个Class<? extends MyT<S, T>> Class<? extends MyT<S, T>> . Class<? extends MyT<S, T>> In test() , you give it a Class<MyTImpl> . test() ,你给它一个Class<MyTImpl> As the compiler checks the bounds, it matches MyT<S, T> against MyTImpl and finds that MyTImpl implements MyT<MySImpl, MyTImpl> , so it can infer MySImpl for S and MyTImpl for T by simply placing those two things alongside. 当编译器检查边界时,它将MyT<S, T>MyTImpl匹配MyT<S, T>并发现MyTImpl实现MyT<MySImpl, MyTImpl> ,因此它可以通过简单地将这两个东西放在一起来推断出MySImplSMyTImpl for T

Then it checks the constraints on S and T for MySImpl and MyTImpl , which succeeds. 然后它检查STMySImplMyTImpl ,然后成功。

In the second example, you ask for a Class<T> . 在第二个示例中,您要求Class<T> The compiler sees Class<MyTImpl> , infers MyTImpl for T , and is done. 编译器看到Class<MyTImpl> ,推断MyTImpl T MyTImpl ,并且完成了。 Failing to infer S , it errors out. 如果没有推断出S ,就会出错。

Constraint checking for T , which could provide the information what S is, doesn't happen. T约束检查可以提供S的信息,但不会发生。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM