我指的是约书亚·布洛赫(Joshua Bloch)的《有效Java》第34项中的范例。我想采用他使用的方法,即让每个相关的enum实现一个基本接口,并从“子枚举”中初始化一个EnumMap。请参阅下面的代码部分。我收到了我不理解的语法错误。我没有设置这种实现方法,但是我想了解为什么它不起作用。

请注意,此示例假定每个类定义都在其自己的文件中。

public interface BaseEnum {
    ...
}

public enum EnumOps1 implements BaseEnum {
    ...
}

public class Widget {
    public Widget() {
         regMap = new EnumMap<EnumOps1, WidgetData>(EnumOps1.class);

         for (EnumOps1 op : EnumOps1.values()) {
             regMap.put(op, getWidgetData(op.key()));  // line with syntax error
         }
    }

    protected Map<? extends BaseEnum, WidgetData> regMap;
}


语法错误详细信息:


  接口java.util.Map <K,V>中放置的方法不能应用于给定类型
    必填:第1个,共?个扩展BaseEnum,WidgetData
    找到:EnumOps1,WidgetData

最佳答案

通配符有问题。您应该将地图声明为Map<BaseEnum, WidgetData>,还应将EnumMap声明为ex。 HashMap<BaseEnum, WidgetData>

关于在SO上为什么如此的原因有很多讨论,但请参见What is PECS (Producer Extends Consumer Super)?

编辑

遗憾的是,您是对的-您不能在此处使用EnumMap。这是因为您正在尝试使用接口,并且EnumMap规定(因为它需要输入T extends Enum<T>类型)它必须只能是Enum。

您的选择基本上归结为

1)使用EnumMap<EnumOps1,...>失去多态性

2)使用HashMap<BaseEnum,...>,一切正常,但必须使用非枚举映射。

3)在尝试使用通配符时,您会遇到我之前链接的PECS限制,例如您可以添加或删除元素,但不能同时添加或删除元素(superextends

10-07 16:31