ArrayList<? extends A> array = new ArrayList<A>();
array.add(new A());
为什么不编译?
答案 0 :(得分:4)
Java教程中的相关部分(http://docs.oracle.com/javase/tutorial/java/generics/wildcardGuidelines.html):
List定义的列表可以非正式地被认为是 只读,但这不是严格的保证。假设你有 以下两节课:
class NaturalNumber { private int i; public NaturalNumber(int i) { this.i = i; } // ... } class EvenNumber extends NaturalNumber { public EvenNumber(int i) { super(i); } // ... }
请考虑以下代码:
List<EvenNumber> le = new ArrayList<>(); List<? extends NaturalNumber> ln = le; ln.add(new NaturalNumber(35)); // compile-time error
由于
List<EvenNumber>
是List<? extends NaturalNumber>
的子类型,因此您可以将le指定给ln。但你不能使用ln来添加 偶数列表的自然数。列表中的以下操作是可能的:
- 您可以添加null。
- 您可以调用清除。
- 您可以获取迭代器并调用remove。
- 您可以捕获通配符并写入您从列表中读取的元素。
您可以看到List定义的列表是 在最严格的意义上不是只读的,但你可能会想到 这样做是因为你无法存储新元素或更改元素 列表中的现有元素。
这里可以找到另一个相关的解释(他的链接也解释了通配符的问题 - http://docs.oracle.com/javase/tutorial/extra/generics/wildcards.html):
...
然而,向它添加任意对象是不安全的:
Collection<?> c = new ArrayList<String>(); c.add(new Object()); // Compile time error
由于我们不知道c的元素类型代表什么,我们不能 添加对象。 add()方法接受类型为E的参数 集合的元素类型。当实际的类型参数是?, 它代表一些未知的类型。我们传递给的任何参数都会 必须是这种未知类型的子类型。因为我们不知道什么 类型,我们不能传递任何内容。唯一的例外是null, 这是每种类型的成员。
另一方面,给定一个List,我们可以调用get()并使用它 结果。结果类型是未知类型,但我们始终知道 它是一个对象。因此可以安全地分配结果 get()到Object类型的变量或将其作为参数传递给 类型对象是预期的。
答案 1 :(得分:0)
您无法将A
添加到List<? extends A>
。为了解决您的问题,您只需将列表声明为
ArrayList<A> array = new ArrayList<A>();
请注意,最好使用声明接口:
List<A> array = new ArrayList<A>();
这使您可以在以后轻松更改具体类型,因为您只需要进行一次更改。
答案 2 :(得分:0)
由于we don't know数组的元素类型代表什么,我们无法向其添加对象。
相反,请使用临时列表:
ArrayList<A> tempArray = new ArrayList<A>();
tempArray.add(new A())
tempArray.add(new A())
ArrayList<? extends A> array = tempArray;
如何使用它的一个例子
//车辆
public abstract class Vehicle {
}
//车
public class Car extends Vehicle {
}
// HandlerVehicle
public class HandlerVehicle {
private List<? extends Vehicle> _vehicles;
public void addVehicles(List<? extends Vehicle> vehicles) {
_vehicles = vehicles;
//perform operations with Vehicle objects
}
}
// HandlerCar
public class HandlerCar {
private HandlerVehicle _handlerVehicle;
private List<Car> _cars;
public HandlerCar() {
_cars = getCars();
_handlerVehicle = new HandlerVehicle();
_handlerVehicle.addVehicles(_cars);
}
private List<Car> getCars() {
return new ArrayList<Car>();
}
}