ski*_*kip 4 java generics wildcard generic-method
我试图解决一个我无法理解部分答案的问题。
以下是课程BackLister:
public class BackLister {
// INSERT HERE
{
List<T> output = new LinkedList<T>();
for (T t : input)
output.add(0, t);
return output;
}
}
Run Code Online (Sandbox Code Playgroud)
问题问哪个可以插入到// 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)
Run Code Online (Sandbox Code Playgroud)
我知道 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)意味着返回类型应该是Listof 的T或其超类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<>();
Run Code Online (Sandbox Code Playgroud)
现在从第一个开始:
A. public static <T> List<T> backwards(List<T> input)
Run Code Online (Sandbox Code Playgroud)
该方法只能接受List<T>并返回List<T>,不能发送listApple和返回listRedApple。(但是,您的返回列表可以包含RedApple,因为它扩展了Apple,但列表的类型必须是List<Apple>,仅此而已)
B. public static <T> List<T> backwards(List<? extends T> input)
Run Code Online (Sandbox Code Playgroud)
你可以发送listRedApple并返回listApple,但你知道那listRedApple是“?extend Apple”,所以在方法体中java将T识别为Apple。然后,如果您使用可以添加元素作为listRedApple参数发送,您可以添加Apple其中listRedApple不正确的元素!所以编译器会避免它并给出编译错误。在 B 中,您只能读取元素(并将其作为 T 获取),但不能向其中添加任何内容。
C. public static <T> List<T> backwards(List<? super T> input)
Run Code Online (Sandbox Code Playgroud)
您可以发送listApple,然后在方法体中您可以添加任何扩展Apple,因为编译器将 T 视为并且在T 的超级Apple列表中,您可以添加任何扩展。
但是这一次,您无法读取任何内容,因为您不知道它的类型,除非您将其获取为. (这是“?超级T”的列表) AppleObject
正如您在这里看到的,两者之间有区别吗?超级和?延长。其中一个为您提供写访问权限,其他为您提供读访问权限。这就是通配符的真正用途。
D. public static <T> List<? extends T> backwards(List<T> input)
E. public static <T> List<? super T> backwards(List<T> input)
Run Code Online (Sandbox Code Playgroud)
如果您发送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)
Run Code Online (Sandbox Code Playgroud)
给出编译错误,因为通配符不能这样使用。
我希望这对你有帮助。
如果有什么问题,任何评论都值得赞赏。
| 归档时间: |
|
| 查看次数: |
1150 次 |
| 最近记录: |