我指的是Joshua Bloch在Effective 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
答案 0 :(得分:4)
这是你的通配符问题。您应该将地图声明为Map<BaseEnum, WidgetData>
,并将您的EnumMap声明为ex。 HashMap<BaseEnum, WidgetData>
有很多关于为什么在SO上如此的讨论,但请参阅What is PECS (Producer Extends Consumer Super)?。
修改强>
可悲的是,你是对的 - 你不能在那里使用EnumMap。这是因为您正在尝试使用接口,并且EnumMap规定(因为它需要类型T extends Enum<T>
)它必须只是一个枚举。
您的选择基本归结为
1)使用EnumMap<EnumOps1,...>
并失去多态性
2)使用HashMap<BaseEnum,...>
,一切正常,但你必须使用非枚举地图。
3)在尝试时使用通配符,但是你会遇到我之前链接的PECS限制,例如:您可以添加或删除元素,但不能同时添加或删除元素(super
与extends
)
答案 1 :(得分:1)
这是我经过数小时研究和尝试后所做的事情。我想要获得EnumMap的好处,并不仅限于一个枚举类,而是仅限于实现相同接口的许多不同类。 在下面的例子中,我有一个名为Layout的接口,我有一些扩展它的枚举类。然后我创建了一个帮助器类Record,它利用EnumMap处理和存储将一些String值映射到我的枚举类中的枚举,我需要它接受不同的枚举类,这些枚举类都扩展了Layout接口。所以我创建了以下类(下面简称为提示):
public class Record<T extends Enum<T> & Layout>
{
private Map<T, String> fields;
/**Constructor accepting the class name of one of the enums implementing layout
*/
public Record(Class<T> layout_type)
{
fields = new EnumMap<T, String>(layout_type);
for (T type : layout_type.getEnumConstants())
{
fields.put(type, "");
}
}
/*Here's an example of a method that manipulates (adds or replaces) an enum map
*item and its corresponding String value in the enum map
*This won't warn any unchecked exceptions or anything and I can pass any
*enum from my enum class that implements layout enum.NAME
*/
public void setRecordFieldValue(final T item, String value)
{
fields.put(item, value);
}
}