java - Java Generic 方法的返回类型中的上界和下界通配符
问题描述
我试图解决一个我无法理解部分答案的问题。
以下是课程BackLister
:
public class BackLister {
// INSERT HERE
{
List<T> output = new LinkedList<T>();
for (T t : input)
output.add(0, t);
return output;
}
}
// INSERT HERE
问题是在类中插入哪个可以BackLister
编译运行不出错?
以下是选项:
A. public static <T> List<T> backwards(List<T> input)
B. public static <T> List<T> backwards(List<? extends T> input)
C. public static <T> List<T> backwards(List<? super T> input)
D. public static <T> List<? extends T> backwards(List<T> input)
E. public static <T> List<? super T> backwards(List<T> input)
F. public static <? extends T> List<T> backwards(List<T> input)
G. public static <? super T> List<T> backwards(List<T> input)
我知道 A 和 B 是正确的,至于for (T t : input)
工作的元素input
应该T
是T
.
但我无法理解为什么D
和E
选项是正确的?
我理解以下内容:
public static <T> List<? extends T> backwards(List<T> input)
表示返回类型应该是List
ofT
或 的子类T
。public static <T> List<? super T> backwards(List<T> input)
表示返回类型应该是List
ofT
或超类T
。
有人可以帮我理解吗?
解决方案
他们每个人之间都有区别,我将解释其中的大部分。让我们从我们的例子开始。我使用这个类层次结构:
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
. (它是“?super 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)
给出编译错误,因为不能像这样使用通配符。
我希望这对你有帮助。
如果有什么问题,任何评论表示赞赏。
推荐阅读
- bash - Hive 使用 HIVE CONCATENATE 合并所有分区
- python - Visual Studio Poll Django 示例执行顺序
- mongodb - ubuntu - 无法远程连接到 mongodb
- angularjs - 未调用 AngularJS 指令链接函数
- ios - Firebase 实时数据库帖子
- distributed-database - Syncer所在的机器坏了,使用TiDB时syncer.meta文件目录丢失
- log4j2 - 如何不重复格式化 log4j2 的参数
- sql - BigQuery Percentile 函数无法在超过 30M 行的分配内存中执行
- java - java.lang.ClassCastException: org.apache.batik.bridge.RhinoInterpreterFactory 与 org.apache.batik.script.InterpreterFactory 不兼容
- session - Redis 会话映射不允许索引