- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我试图解决一个我无法理解部分答案的问题。
以下是类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
的 T
或子类 的 T
. public static <T> List<? super T> backwards(List<T> input)
意味着返回类型应该是 List
的 T
或者T
的父类(super class).谁能帮我理解一下?
最佳答案
它们之间各有不同,我将解释其中的大部分。让我们从我们的例子开始。我使用这个类层次结构:
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
是 "? extend Apple" 所以在方法体中 java 将 T 识别为 Apple。然后,如果您使用可以在 listRedApple
中添加元素作为参数发送的,您可以添加 Apple
在 listRedApple
这不是真的!所以编译器避免它并给出编译错误。在 B 中,您只能读取元素(并将其作为 T 获取),但不能向其中添加任何内容。
C. public static <T> List<T> backwards(List<? super T> input)
您可以发送listApple
然后在方法主体中,您可以添加任何扩展 Apple
因为编译器将 T 视为 Apple
在 T 的 super 元素 列表中,您可以添加任何扩展 Apple
.
但是这一次,您无法读取任何内容,因为您不知道它的类型,除非您将其作为 Object
获取。 . (是"?super T"的列表)
如您所见, 之间有区别吗? super 和?延伸。其中一个为您提供写入权限,另一个为您提供读取权限。这才是通配符的真正用途。
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>
对于 'E 和 List<? super Apple>
对于 D
并将它们发送到需要它们作为参数的方法。
F. public static <? extends T> List<T> backwards(List<T> input)
G. public static <? super T> List<T> backwards(List<T> input)
给出编译错误,因为不能这样使用通配符。
希望对你有帮助。
如果有什么不对,欢迎提出任何意见。
关于java - Java泛型方法返回类型中的上界和下界通配符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53010162/
我是一名优秀的程序员,十分优秀!