假设:
import java.util.*;
public class Hancock {
//insert code here
list.add("foo");
}
}
在第5行独立插入的两个代码片段将在没有警告的情况下编译? (选择两项)
A. public void addString(List list) {
B. public void addString(List<String> list) {
C. public void addString(List<? super String> list) {
D. public void addString(List<? extends String> list) {
正确答案是B&amp;下进行。
答案A和B对我来说非常清楚。对于答案C&amp;我知道继承的方式是什么,但是我无法理解为什么答案D不会在Eclipse中编译而其他所有人都这样做(A有关于通用的警告,B&amp; C没有warrings)。
Eclipse中答案D的错误是The method add(capture#1-of ? extends String) in the type List<capture#1-of ? extends String> is not applicable for the arguments (String)
。
另一方面,这编译:
public void addString() {
List<? extends String> list1 = new ArrayList<String>();
List<? super String> list2 = new ArrayList<String>();
}
为什么呢?为什么<? super String>
在变量声明中编译时不会在方法声明中编译。
我知道String
是最后一堂课,不能被任何其他班级扩展,但这并没有向我解释这里发生了什么。
答案 0 :(得分:9)
首先,让我们看一下答案C:
public void addString(List<? super String> list) {
list.add("foo");
}
此方法声明表示您将被允许传递List
个对象,这些对象由某些超级String
参数化,例如String
或Object
。所以:
List<String>
,则list.add("foo")
将完全有效。List<Object>
,则list.add("foo")
将完全有效,因为&#34; foo&#34;是String
(您可以将String
添加到List<Object>
)。这意味着答案C是正确的。
现在让我们看看答案D.
如果你有这样的方法声明:
public void addString(List<? extends String> list) {
}
这意味着您将能够传递List
某些未知子类型String
参数化的对象。因此,当您执行list.add("foo");
时,编译器不会意识到所提供的对象是否具有与String
的 unknown 子类型匹配的类型,因此会引发编译 - 时间错误。
当你有:
public void addString() {
List<? extends String> list1 = new ArrayList<String>();
List<? super String> list2 = new ArrayList<String>();
}
此片段编译得很好,因为list1
被定义为保存List
某些未知子类型的String
对象,包括String
本身,这就是为什么它#39;有效。
问题是,您无法添加任何内容,null
除外。
对于list2
,变量可以容纳List
个对象,这些对象由某些超类型String
参数化,包括String
本身。
更多信息:
答案 1 :(得分:2)
首先,仿制药并不关心String
是最终的。它们对最终和非最终课程的工作方式相同。
考虑到这一点,应该明白为什么不允许D - 如果是,你可以这样做:
void test() {
List<Integer> integers = new ArrayList<Integer>();
addADouble(integers);
int a = integers.get(0); // ????
}
void addADouble(List<? extends Number> list) {
list.add(new Double(5.0));
}
List<? extends Number>
是一个扩展数字的内容列表,但您并不确切知道它的列表是什么。&#34; - 它可能是List<Double>
,List<Integer>
,List<Number>
或List<YourCustomSubclassOfNumber>
,因此您无法添加任何内容,因为您没有&# 39;不知道它是否是正确的类型。