java与<>的区别?方法和变量声明中的超级/扩展字符串>
鉴于:
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&;C
答案A和B对我来说很清楚。有关答案,请参阅C& ;;我知道继承的方向,但是我不理解为什么答案D没有在Eclipse中编译,而其他的都编译(A有关于泛型的警告,B&C没有警告)
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
是最后一个类,不能被任何其他类扩展,但这并不能向我解释这里发生了什么
# 1 楼答案
首先,让我们看看答案C:
此方法声明表示将允许您传递
List
对象,这些对象由String
的某个超类参数化,例如String
或Object
。因此:List<String>
,list.add("foo")
将完全有效李>List<Object>
,list.add("foo")
将完全有效,因为“foo”是一个String
(您可以将String
添加到List<Object>
)李>这意味着答案C是正确的
现在让我们看看答案D
如果您有这样的方法声明:
这意味着您将能够传递
List
对象,这些对象由String
的某个未知子类型参数化。因此,当您执行list.add("foo");
操作时,编译器不会知道提供的对象是否具有与String
的未知子类型匹配的类型,因此会引发编译时错误如果您有:
这个片段编译得很好,因为,您将无法添加任何内容
list1
被定义为保存List
对象,这些对象属于String
的某些未知子类型,包括String
本身,这就是它有效的原因。 问题是,除了^{至于
list2
,变量可以保存List
对象,这些对象由一些超类型的String
参数化,包括String
本身更多信息:
# 2 楼答案
首先,泛型并不关心
String
是最终的。他们对期末和非期末课程的学习方式相同考虑到这一点,应该很清楚为什么不允许D—如果允许,您可以这样做:
List<? extends Number>
是一个“扩展数字的事物列表,但您不确切知道它是什么。”它可能是List<Double>
、或List<Integer>
、或List<Number>
、或List<YourCustomSubclassOfNumber>
,因此您无法向它添加任何内容,因为您不知道它是否是正确的类型