假设我有两个班级:
public class Bike {}
public class MountainBike extends Bike {}
当我按如下方式创建方法时,它不会抛出任何错误:
Bike mountainBike = new MountainBike();
// method signature is addBike(Bike bike);
addBike(mountainBike);
但如果我尝试以下内容:
Set<MountainBike> bikes = new HashSet<MountainBike>();
// method signature is addBikes(Set<Bike> bikes);
addBikes(bikes);
我收到错误的方法签名匹配错误。如何创建包含子类的Set?
答案 0 :(得分:5)
你想要这个:
addBikes(Set<? extends Bike> bikes)
另外,正如@Blacklight所指出的那样,Set
本身就是一个接口,所以你不能直接实例化它(你需要实例化它的一个具体实现,例如HashSet
,{{1 }},或LinkedHashSet
)。
这里的关键点是TreeSet
不是Set<MountainBike>
的子类型 - 特别是,您可以将自行车以外的自行车添加到一组自行车中,但不能添加到一组山地自行车上。因此,出于类型安全的原因,Java会阻止您将Set<Bike>
传递给期望Set<MountainBike>
的方法,因为否则您将能够在方法中向该集合添加非山地自行车没有它被编译器标记(它会导致运行时错误)。
作为一个额外的观察,请注意不可变的山地自行车套装将是不可变的自行车套装 - 这是导致此问题的可变性。这与可以用其他语言(特别是C#)表达的类型参数的协方差和逆变的概念联系在一起。