为什么编译器在具有双界泛型类型时不将T(interface)推断为实现T的类?

我有一个类 CBound,它实现了两个接口 IBound1 和 Ibound2:

class CBound implements IBound1, IBound2 {}

我有一个通用方法,它接受一个实现 IBound1 和 Ibound2 接口的类类型作为类型参数:

 public static <T extends IBound1 & IBound2> void getData(T list) {
      //Some code...
}

我用 CBound 类的实现创建了一个 IBound1 类型的对象:

 IBound1 a = new CBound();
 getData(a); // doesn't work

为什么 obj a 不能作为 getData() 的参数?

当我更改代码时:

CBound b = new CBound();
getData(b); // It works fine

回答

编译器必须在编译时推断出T满足边界的。

当您传入时a,编译器只知道它a的类型IBound1。由于该方法的参数也是T,因此编译器实际上只有两种选择T——IBound1或者Object——两者都不满足边界。

你可能会问,“为什么编译器不推断TCBound这样?” 好吧,表达式getData(a)中没有任何类型的内容CBound。即使我们通过阅读前面的代码行知道a实际上是指一个类型的对象CBound,编译器在推断T. 并且即使T推断为CBound,您也无法传递a给类型为 的参数CBound

b然而,在 的情况下,编译器非常清楚它b的类型CBound(因为您已经声明了它),因此它可以成功推断TCBound

  • Exactly as @Sweeper said. I would just add that when the compiler statically analyzes your code doesn't know that `a` is `CBound`, which is the dynamic type of the object, it just knows the static type `IBound1`. It would work if you typecast it. `getData((CBound) a)`
  • `a` is of type `IBound1` (as far as the compiler is concerned). If `T` were `CBound`, the parameter type of `getData` would be `CBound` too. You can't pass an expression to a parameter when that parameter's type is the expression's subtype. Like how you can't pass a `List` to a method accepting `ArrayList`.

以上是为什么编译器在具有双界泛型类型时不将T(interface)推断为实现T的类?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>