Java集合:将子集合作为父集合传递

假设我有一个接口和一些类:

public interface IPanel { public void addComponents(Set components); public ComponentType create(); } public class Button extends Component { } public class LocalizedButton extends Button { } public class ButtonsPanel implements IPanel

然后我有一组LocalizedButtons,当我打电话

 final LocalizedButtonsPanel localizedButtonsPanel = new LocalizedButtonsPanel(); final Set localizedButtonsSet = new LinkedHashSet(); localizedButtonsPanel.addComponents(localizedButtonsSet); 

我知道这个方法不适用于这个参数。 如果我尝试在LocalizedButtonsPanel将此方法重载为addComponents(Set buttons) ,我当然会得到类型擦除。

可能是某些模式被遗漏或存在处理此架构以实现正确添加LocalizedButtons集的技巧?


我得到了答案,我想让我的例子更具体 – 我的实现中有一些validation器,所以我需要将集合类型也存储为generics,这是我使用答案得到的简化代码:

 public interface IPanel<ComponentType extends Component, CollectionType extends Collection> extends Validated { public void addComponents(CollectionType components); public ComponentType create(); } public class Button extends Component { } public class LocalizedButton extends Button { } public class ButtonsPanel implements IPanel<Button, Set> { public void addComponents(Set components) { ... /* uses create() */ ; } public Button create() { return new Button(); } } public class LocalizedButtonsPanel extends ButtonsPanel { public Button create() { return new LocalizedButton(); } } 

在这种情况下,它的工作原理

将addComponents()签名更改为

 public void addComponents(Set components) 

这样方法接受Button的子类集。 这样,您可以将Set作为参数传递,因为LocalizedButton扩展了Button ,因此匹配参数Type of Set Set

你有

 public class ButtonsPanel implements IPanel 

应该

 public class ButtonsPanel implements IPanel 

该列表仅针对不适用于扩展该类型的Object的按钮类型创建。

参数化类型在Java中不协变。 这很好,否则你可以将一个狗添加到已经被上传到List 的List 。 您可以在使用地点添加协方差,例如List <? extends Animal>可以分配一个List ,你不能调用它的add方法。