考虑以下示例,
class ClsA {}
class ClsB {}
interface IntA {}
interface IntB {}
我有两种非常相似的方法:
static <T extends ClsA> T returnC() { // Here T extends the class
return null;
}
static <T extends IntA> T returnI() { // Here T extends the interface
return null;
}
然后该方法调用:
ClsA ac = returnC(); // This works fine based on inference.
IntA ai = returnI(); // Similarly this works fine based on inference.
但考虑以下2:
ClsB bc = returnC(); // ERROR as expected.
Eclipse错误:
绑定不匹配:Testing类型的泛型方法returnC()不适用于参数()。推断出的类型ClsB&ClsA不是有界参数
<T extends ClsA>
的有效替代品
但以下代码编译良好:
IntB bi = returnI(); // Works fine
为什么对于接口,泛型绑定在返回类型中不被考虑
这里的神奇词汇是raws和多重继承。
让我们先来看看你的returnC
方法:
static <T extends ClsA> T returnC() {
return null;
}
类型T
与ClsA
有界,这意味着如果调用rawreturnC
方法,则返回类型将仅为ClsA
。
如果您有以下语句:ClsA ac = returnC();
,编译器将成功编译,因为方法的raw返回类型是ClsA
,它与ac
的类型兼容。
原始返回类型也是语句ClsB bc = returnC();
不编译的原因。
现在让我们来看看returnI
方法:
static <T extends IntA> T returnI() { // Here T extends the interface
return null;
}
这里,type参数仅绑定到IntA
。
然而,这并不意味着T
的替换类型必须仅实现IntA
——类型可以同时实现IntA
和IntB
。允许像IntB bi = returnI();
这样的语句,因为一个类型可以实现多个接口,但不能实现多个类。
考虑这个类别:
class SomethingReallyCool implements IntA, IntB { }
该类型是returnI()
的类型参数的有效替代品,其证明如下:
IntB bi = YourClass.<SomethingReallyCool>returnI();
为什么?因为它是一个实现IntA
的类,而这是编译器唯一关心的事情。