从逻辑上讲,double sumOfList(List<? extends Double> list) 会使函数变成只读模式,为什么list.remove()可以编译成功

Logically,double sumOfList(List<? extends Double> list) will make the function become read-only mode , why list.remove() can be compiled successfully

逻辑上,static double sumOfList(List<? extends Double> list)会让函数变成只读模式,那为什么list.remove()可以编译成功

public class Extend_char {
    public static void main(String[] args) {
        {
        List<Double> list = new ArrayList<>();        
        list.add(1.2);        
        list.add(2.2);        
        list.add(3.2);        
        System.out.println(sumOfList(list));                
        System.out.println(list);    
}
    static double sumOfList(List<? extends Double> list) {
        double sum = 0;        
            for (int i=0; i<list.size(); i++) {
            double n = list.get(i);            
            sum = sum + n;        
            }
            //list.add(new Double(5.5));  Cannot compile and call normally                    
            list.remove(2.2);   //Can compile and call normally        
            return sum;    
    }
}

Logically,static double sumOfList(List<? extends Double> list) will make the function become read-only mode

看,这就是编程的问题。它太复杂了 - 所以我们提供过于简单的解释。

你是这件事的受害者。 List<? extends Double> 不是 一个 'read only list'。

但我可以看到试图提供帮助的人是如何告诉你的。

看,List<? extends Something> 的意义在于它可以让您提供 List<Something>List<SomeChildOfSomething>IF 然后可以在这样的事情上调用 .add(instanceOfSomething),这是个问题。

想象一下这个方法:

void foo(List<? extends Number> list) {
   list.add(5); // an integer
}

List<Double> listOfDoubles = new ArrayList<Double>();
foo(listOfDoubles);
listOfDoubles.get(0); // oh dear. Now what?

看到问题了吗?一个解决方案是确保 所有除非知道精确类型 才会失败的方法都是不允许的。 add就是这样一种方法。出于显而易见的原因,addAllset 也是如此。你不能调用那些,除非你知道列表是你传递给那些方法的表达式的确切类型,或者它的超类型(这就是为什么你 can 调用.add上一个List<? super Double>就好了)。

但是修改列表的方法 而不是 会导致此类问题 - 基本上所有不采用 T 类型元素(集合)的方法,例如 .clear().remove()removeIf、等等?

这些都很好。

TL;DR:List<? extends AThingie> 不是 'a read only list'。那是完全错误的。这是一个可以理解但过于简单化的解释。不要对谁告诉你的太苛刻了。