Java 我可以在列表声明中使用泛型通配符吗?
考虑以下代码:Java 我可以在列表声明中使用泛型通配符吗?,java,generics,arraylist,wildcard,Java,Generics,Arraylist,Wildcard,考虑以下代码: class Super {} class Sub extends Super {} class Test { public static void main(String[] args) { List<? extends Super> list = new ArrayList<Sub>(); //1 list.add(new Sub()); //2 } } class Super{} 类Sub扩展了Supe
class Super {}
class Sub extends Super {}
class Test {
public static void main(String[] args) {
List<? extends Super> list = new ArrayList<Sub>(); //1
list.add(new Sub()); //2
}
}
class Super{}
类Sub扩展了Super{}
课堂测试{
公共静态void main(字符串[]args){
列表
1) 为什么第1行成功编译
第一行是编译的,因为List
是List的子类,第1行中的捕获声明在方法参数中很好。请参阅。如果您需要一个扩展了Super
的列表,只需使用List就可以将列表
声明为,它可以分配给Super
的任何子类型>所以,分配一个子类型列表是可以的,编译器允许编译。但这并不意味着,您可以向其中添加特定的对象类型
1) 为什么第1行成功编译
您基本上将列表定义为包含扩展(或是)Super
的任何类型的元素,即编译器知道该列表中的每个元素至少应具有Super
的属性
由于Sub
是Super
的子类,因此任何仅包含Sub
元素的列表也满足所有元素都是Super
实例的要求,列表
1) 为什么第1行成功编译
您将list
声明为“从Super
派生的事物的列表”。您将Sub
的列表分配给它。Sub
是“从Super
派生的事物”
2) 第1行是声明列表(或其他集合)的良好实践吗
不可以。通配符用于函数参数。局部变量在其泛型参数中应尽可能具体,以避免出现类似您所面临的问题
3) 为什么在第1行中列表被声明为Sub类型后,第2行编译失败
谬误。list
被声明为包含“源自Super
”的元素,而不是您声称的Sub
。并且您不能将Sub
添加到列表中,因为“某物”可能不是Sub
;可能是Sub2
,添加将等同于此非法分配:
class Super {}
class Sub extends Super {}
class Sub2 extends Super {}
Sub2 s = new Sub();
这里的主要误解似乎是,您认为通配符在赋值时会被替换。事实并非如此。它仍然是一个通配符,并且只进行了兼容性检查
4) Eclipse的自动完成功能说现在列表中只允许“null”元素。为什么
null
是任何可能引用类型的唯一值,因此,无论通配符代表什么,它都与列表兼容。Ok如果元素类型单一且安全,编译器必须将元素类型限制为null(因为直到运行时它才知道是什么)你可以使用List
来保存Super
的多个子类型的元素。但是,这样你就无法将其初始化为ArrayList
。然后你必须将其实例化为List List=new arrarylist()
和null
是允许的,因为null属于所有引用类型。感谢这些引用-PECS规则真的很有帮助!是的,它是Joshua Bloch在他的《有效的Java》一书中给出的。这是一本很棒的书。也请阅读一下。很高兴能提供帮助。
class Super {}
class Sub extends Super {}
class Sub2 extends Super {}
Sub2 s = new Sub();