为什么不能添加到列表<?在Java中扩展String>?

Bri*_*dha 2 java generics arraylist

在下面的代码段中,将“ Hulooo”添加到列表中会生成编译器错误,因为String不会扩展String。但是,对字符串的ArrayList进行类型转换是可行的。但是类型转换对象的ArrayList不起作用。

有人可以解释为什么会这样吗?什么适用于String(在这种情况下)而不适用于Object?

public static void takeList(List<? extends String> list)
{
    list.add("Hulloo");//ERROR
    list=new ArrayList<String>();
    list=new ArrayList<Object>();//ERROR
}
Run Code Online (Sandbox Code Playgroud)

Hoo*_*pje 5

问号?是所谓的通配符。List<? extends String>装置:任何类型的List<T>,其中TString或子类型的StringString是最后一个类,因此没有的子类型String,但是编译器没有考虑这一点。因此,编译器假定该列表可能是的某些子类型的列表String,并且不可能将Strings 添加到此类列表中。

让我们用一个非最终类模拟您的示例,该类A具有一个子类B

class A { 
    // empty
}

class B extends A {
    void f();
}
Run Code Online (Sandbox Code Playgroud)

现在考虑与您的方法等效的方法:

public static void takeList(List<? extends A> list) {
    list.add(new A());
}
Run Code Online (Sandbox Code Playgroud)

由于以下原因,它将无法编译。假设您按以下方式调用此方法:

List<B> myList = new ArrayList<>();   // line 1
takeList(myList);                     // line 2
B element = myList.get(0);            // line 3
B.f();                                // line 4
Run Code Online (Sandbox Code Playgroud)

因为BA函数的子类,所以第2行中的调用是合法的。但是该方法takeList会将A而不是添加到列表中B。然后的列表B包含一个非元素B,第3和第4行细分。

那里有类型系统来防止键入错误,因此,在一种情况下,您可以将错误类型的对象添加到列表中,类型系统必须禁止它。