超级和扩展行为相同

时间:2014-10-26 18:34:04

标签: java oop generics collections

以前可能会以不同的格式提出这个问题,但我找不到合适的答案。

这些代码之间的区别是什么:

第一个代码

ArrayList<? super Number> list=new ArrayList<>(Arrays.asList(1));

第二个代码

ArrayList<? extends Number> list=new ArrayList<>(Arrays.asList(1));

两个声明都编译。请证明前者编纂的原因。它显示Integer扩展Number和Integer超级数。

修改::

我期待的答案是: new ArrayList(Collection<? extends E>)因此他们都编译。

以这种方式,这不是一个重复的问题,因为所提到的答案没有描述这一点。

2 个答案:

答案 0 :(得分:0)

它们都以相同的方式执行,但编译器会阻止它们以不同的方式进行编译。

public class NewClass {

    private List<? super Number> supers;

    private List<? extends Number> extenders;

    public NewClass() {
        supers = new ArrayList<>();
        extenders = new ArrayList<>();
    }

    public void addSupers() {
        supers.add(new Integer("5"));
    }

    public void addExtenders() {
        // This won't compile
        extenders.add(new Integer("5"));
    }

    public void getSupers() {
        // this won't compile
        Number number = supers.get(1);
    }

    public void getExtenders() {
        Number number = extenders.get(1);
    }

}

supers添加案例中,您可以安全地添加Integers,因为Integers拥有超级Number。您无法在extenders情况下执行此操作,因为扩展程序包含 Number的特定子类,在这种情况下由通配符确定。简而言之,通常假定extenders项包含所有相同的Number子类。

supers获取案例中,您无法安全地提取Number,因为对于某些类型,可能不是Numbers,而是Number的超类,所以&#34;向下演员&#34;很危险但是,在extenders方案中,所有内容都被确保为Number的子类,因此可以安全地将它们转换为Number

答案 1 :(得分:0)

<? super Number>表示该类型是Number的任何超类。

<? extends Number>表示该类型是Number的任何子类。

他们会编译到相同的东西,但这取决于您实际使用List的类型。

如果你有一个List<? super Number>,你可以把任何Number放进去,但编译器不能保证你得到的东西是{{1} }}。如果您有Number,那么您获得的任何内容都肯定会从List<? extends Number>继承。

如果尝试将Number传递给期望List<? super Number>的方法,编译器将会反对,因为前者可能包含的内容不是List<? extends Number>

如果尝试将Number传递给期望List<? extends Number>的方法,编译器将会反对,因为前者无法接收后者可以使用的元素。