在LinkedHashMap中使用一个接受其子类作为值的类

时间:2015-08-24 13:13:20

标签: java generics hashmap

很抱歉,如果这是一个愚蠢的问题,但我已经搜索了很长时间,并且无法理解为什么下面的代码会引发编译错误:

我有一个名为MenuElement的第一个类,它是几个子类的父类。它有两种方法:

class MenuElement {
   public int getType() {};
   public long getId() {};
   ... 
}

在另一个类中,我声明为属性:

private LinkedHashMap<Integer, LinkedHashMap <Long, ? extends MenuElement>> mMenuElement;

在其中一个方法中,我有这个,但编译器不能接受menuElement作为MenuElement的一个孩子:

public void onMenuElementActivationChanged(MenuElement menuElement) {
...
    mMenuElement.get(menuElement.getType()).put(menuElement.getId(), menuElement);
...
}

我觉得我可能会错过java的泛型逻辑。有人可以帮忙吗? 谢谢! :)

2 个答案:

答案 0 :(得分:0)

这是仿制药中常见的错误。

通用的参数列表必须完全匹配才能编译。因此<? extends X> 匹配X,因为X不会extend X。以下工作正常。

abstract class MenuElement {

    public abstract int getType();

    public abstract long getId();
}

public void test() {
    LinkedHashMap<Integer, LinkedHashMap <Long, MenuElement>> mMenuElement = new LinkedHashMap<>();
    MenuElement me;
    mMenuElement.get(me.getType()).put(me.getId(), me);

非常非常不寻常需要在泛型中使用<? ...>。在大多数情况下,真正的类型是好的。普通规则无论如何都适用于泛型类型匹配 - 即,当泛型被定义为接受B extends A时,仍然可以使用类型为B implements AA的对象。

例如:

private static class X {

    public X() {
    }
}

private static class Y {

    public Y() {
    }
}

private static class Z extends Y {

    public Z() {
    }
}

public void test() {
    Map<X, Y> map = new HashMap<>();
    // Both of these work fine.
    map.put(new X(), new Y());
    map.put(new X(), new Z());
}

答案 1 :(得分:0)

您发布的错误消息表明您使用的是ArrayList而不是LinkedHashMap。该定义要求外部地图具有Integer-&gt; LinkedHashMap。请检查构建mMenuElement实例的代码,看看是否可以用Map替换该ArrayList。

reason: actual argument LinkedHashMap<Integer,ArrayList<? extends MenuElement>> cannot be converted to LinkedHashMap<Integer,LinkedHashMap<Long,? extends MenuElement>> by method