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

时间:2010-08-03 11:53:17

标签: java generics collections

说我有一个界面和一些类:

public interface IPanel<ComponentType extends Component> {
   public void addComponents(Set<ComponentType> components);
   public ComponentType create();
}

public class Button extends Component { }

public class LocalizedButton extends Button { }

public class ButtonsPanel implements IPanel<Button> {
    public void addComponents(Set<Button> components) { ... /* uses create() */ ; }
    public Button create() { return new Button(); }
}

public class LocalizedButtonsPanel extends ButtonsPanel {
    public Button create() { return new LocalizedButton(); }
}

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

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

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

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


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

public interface IPanel<ComponentType extends Component, CollectionType extends Collection<? extends Component>> extends Validated<CollectionType> {
   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<? extends Button>> {
    public void addComponents(Set<? extends Button> components) { ... /* uses create() */ ; }
    public Button create() { return new Button(); }
}

public class LocalizedButtonsPanel extends ButtonsPanel {
    public Button create() { return new LocalizedButton(); }
}

在这种情况下,它可以正常工作

3 个答案:

答案 0 :(得分:6)

将addComponents()签名更改为

public void addComponents(Set<? extends Button> components)

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

答案 1 :(得分:5)

你有

public class ButtonsPanel implements IPanel<Button> {
    public void addComponents(Set<Button> components) { ... /* uses create() */ ; }
    public Button create() { return new Button(); }
}

应该是

public class ButtonsPanel implements IPanel<Button> {
    public void addComponents(Set<? extends Button> components) { ... /* uses create() */ ; }
    public Button create() { return new Button(); }
}

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

答案 2 :(得分:0)

参数化类型在Java中不协变。这很好,否则您可以将狗添加到列表&lt; Cat&gt;那已被上传到List&lt; Animal&gt;。您可以在使用地点添加协方差,例如,列表&lt;?延伸动物&gt;可以分配一个List&lt; Cat&gt;而且你不能调用它的add方法。