java 泛型、通配符和通配符子类型 - naturalNumberList.add(new EvenNumber(20));产生错误信息

java generic, wildcard and wildcard subtyping - naturalNumberList.add(new EvenNumber(20)); produces error message

我目前正在学习 java 泛型、通配符和通配符子类型化。我想出了以下代码。但是,当我尝试使用这行代码 naturalNumberList.add(new EvenNumber(20));EvenNumber 的实例添加到列表时,显示了一条神秘的错误消息(见附图)。

有人可以向我解释一下为什么 naturalNumberList.add(new EvenNumber(20)); 会产生错误吗?在此先感谢您的帮助!

public class NaturalNumber {
    private int i;
    public NaturalNumber(int i){
        this.i = i;
    }
}
class EvenNumber extends NaturalNumber {
    public EvenNumber(int i){
        super(i);
    }
}

class PSVM {
    public static void main(String[] args) {
        List<EvenNumber> evenNumberList = new ArrayList<>();
        List<? extends NaturalNumber> naturalNumberList = evenNumberList;
        evenNumberList.add(new EvenNumber(100));
        naturalNumberList.add(new EvenNumber(20));//error, for error message, see picture attached below
    }
}

错误信息:

它在这里的表现完全与您想象的不同。

这实际上意味着变量可以保存列表实例List<NaturalNumber>或其任何子类。

现在编译器不允许你添加,因为它可能是一些其他子类的列表,如List<OddNumber>


通配符的真正用途是增加方法参数的灵活性。

public void method(List<? extends NaturalNumber> list) 

您将无法向列表中添加任何内容,只能使用其现有元素。要允许添加,您必须使用:

public void method(List<? super NaturalNumber> list) 

这里无法保证元素的类型,只能取Objects

Remember the rule: PECS. Producer extends, consumer super.

如果您希望既能取又能加,则不能使用通配符。