3 回答

TA贡献1833条经验 获得超4个赞
它们中的每一个都存在差异,我将解释其中的大部分。让我们从我们的例子开始。我使用这个类层次结构:
class Food {}
class Apple extends Food {}
class Orange extends Food {}
class RedApple extends Apple {}
List<Food> listFood = new ArrayList<>();
List<Apple> listApple = new ArrayList<>();
List<Orange> listOrange = new ArrayList<>();
List<RedApple> listRedApple = new ArrayList<>();
现在从第一个开始:
A. public static <T> List<T> backwards(List<T> input)
这个方法只会接受List<T>和返回List<T>,你不能发送listApple和返回listRedApple。(但是您的返回列表可以包含,RedApple因为它扩展Apple但列表类型必须是List<Apple>,没有别的)
B. public static <T> List<T> backwards(List<? extends T> input)
您可以发送listRedApple和返回,listApple但您知道这listRedApple是“?扩展 Apple”,因此在方法主体中 java 将 T 识别为 Apple。然后,如果你使用可以添加的元素listRedApple,其发送作为参数,你可以添加Apple在listRedApple其中是不正确的!所以编译器避免它并给出编译错误。在 B 中,您只能读取元素(并将其作为 T 获取),但不能向其中添加任何内容。
C. public static <T> List<T> backwards(List<? super T> input)
您可以发送listApple,然后在方法主体中添加任何扩展,Apple因为编译器将 T 视为 TApple的任何列表,并且在T的任何超列表中,您可以添加任何扩展Apple。
但是这一次,您无法读取任何内容,因为您不知道它的类型,除非您将其作为Object. (这是一个“?超级T”的列表)
正如你在这里看到的,有区别吗?超级和?延伸。其中之一为您提供写访问权限,另一个为您提供读访问权限。这就是通配符的真正用途。
D. public static <T> List<? extends T> backwards(List<T> input)
E. public static <T> List<? super T> backwards(List<T> input)
如果您发送listApple然后您返回,List<? extends Apple>但您可以将它分配给任何listFood或listApple或listRedApple因为List<? extends Apple>可能包含Apple或RedApple或其他东西,我们不能将它分配给任何List<T>因为然后我们可以添加T到该列表中,并且可能T和? extends T不一样。这对D和都是一样的E。您可以将其分配给List<? extends Apple>for 'E 和List<? super Apple>forD并将它们发送到需要它们作为参数的方法。
F. public static <? extends T> List<T> backwards(List<T> input)
G. public static <? super T> List<T> backwards(List<T> input)
给出编译错误,因为不能像这样使用通配符。
我希望这对你有帮助。
如果有什么问题,任何评论都表示赞赏。

TA贡献1780条经验 获得超1个赞
选项D和E是有效的,因为泛型类型之间存在超子类型关系,允许您定义方法可以接受或返回的更大的类型集。
因此,以下是有效的 (D):
public static <T> List<? extends T> backwards(List<T> input) {
return List.of();
}
// there exist a super-subtype relationships among List<? extends Number> and List<Long>
List<? extends Number> list = backwards(List.<Long>of(1L, 2L));
因为该类型Long是通配符所? extends Number表示的类型家族的成员(作为其子类型的类型家族Number和类型Number本身)。
下一个代码片段也是有效的 (E):
public static <T> List<? super T> backwards(List<T> input) {
return List.of();
}
List<? super Long> ints = backwards(List.<Long>of(1L, 2L));
因为该类型Long是通配符所? super Long表示的类型家族的成员(作为超类型的类型家族Long和类型Long本身)。
所以,你的理解是对的。

TA贡献1876条经验 获得超7个赞
下图描述了泛型中的子类型关系:
List<T> is a subtype of List<? super T>
Also List<T> is a subtype of List<? extends T>
这就是为什么选项 D 和 E 是正确的。
您可以参考该页面:https : //docs.oracle.com/javase/tutorial/java/generics/subtyping.html
添加回答
举报