Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/390.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 我可以在列表声明中使用泛型通配符吗?_Java_Generics_Arraylist_Wildcard - Fatal编程技术网

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();