这是我的计划.我不知道为什么我会收到编译时错误.
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(String[] args) {
List< ? extends Number > list = new ArrayList<Integer>();
list.add(6); // Compile Time Error
System.out.println(list);
}
}
Run Code Online (Sandbox Code Playgroud)
但是以下程序运行正常
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(String[] args) {
List< ? super Number > list = new ArrayList<Number>();
list.add(6);
System.out.println(list);
}
}
Run Code Online (Sandbox Code Playgroud)
Eclipse出错:
以下是Eclipse的错误描述:
类型List中的方法add(int,capture#1-of?extends Number)不适用于参数(int)
ver*_*ald 18
这是因为你在第一种情况下所做的事情并不是类型安全的.您已声明list为List"某个子类Number",然后尝试在其中插入一个Integer.绝对不能保证Integer与基础列表的实际运行时类型兼容.编译器在这里阻止你,因为你正在做的事没有任何意义.
考虑一下,作为极端的例子:
List< ? extends Object > list = new ArrayList<Integer>();
list.add("Hello, World!");
Run Code Online (Sandbox Code Playgroud)
如果这个工作,你会有List<Integer>一个String在其中!
如果你真的希望它能够工作,你必须通过强制转换告诉编译器你知道你在做什么:
((List<Integer>)list).add(6);
Run Code Online (Sandbox Code Playgroud)
但即便如此,您仍会收到关于类型安全的警告.
第二种情况是有效的,因为列表保证是"数字的一些超类".Integer是它的子类Number,因此它可以隐式转换为任何超类(包括Number它自己),因此不存在该值与列表的实际类型不兼容的风险.
有关详细信息,您可能需要阅读协方差和逆变之间的差异.