为什么编译器在具有双界泛型类型时不将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——两者都不满足边界。
你可能会问,“为什么编译器不推断T是CBound这样?” 好吧,表达式getData(a)中没有任何类型的内容CBound。即使我们通过阅读前面的代码行知道a实际上是指一个类型的对象CBound,编译器在推断T. 并且即使T推断为CBound,您也无法传递a给类型为 的参数CBound。
b然而,在 的情况下,编译器非常清楚它b的类型CBound(因为您已经声明了它),因此它可以成功推断T为CBound。
- 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`.
THE END
二维码