I’m referring to the paradigm in Item 34 in Effective Java by Joshua Bloch. I would like to take the method he’s using which is to have each related enum implement a base interface, and initialize an EnumMap from the “sub-enums.” See the code section below. I’m getting a syntax error which I don’t understand. I’m not set on this method of implementation, but I would like to understand why it won’t work.
Note that this example assumes each class definition is in its own file.
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;
}
Syntax error detail:
method put in interface java.util.Map
<K,V>cannot be applied to given types
required: capture#1 of ? extends BaseEnum, WidgetData
found: EnumOps1, WidgetData
It’s a problem with your wildcarding. You should declare your map as
Map<BaseEnum, WidgetData>and also your EnumMap as ex.HashMap<BaseEnum, WidgetData>There’s plenty of discussion of why this is true on SO, but see What is PECS (Producer Extends Consumer Super)? for example.
Edit
Sadly, you’re right – you can’t use an EnumMap there. This is because you are trying to use an interface, and EnumMap stipulates (as it requires a type
T extends Enum<T>) that it must be an Enum only.Your choices basically boil down to
1) Use an
EnumMap<EnumOps1,...>and lose out on the polymorphism2) Use a
HashMap<BaseEnum,...>and everything works fine but you have to use a non-Enum map.3) Use wildcards as you are trying, but you’ll run into the PECS restrictions I linked earlier e.g. you can add or remove elements but not both (
supervsextends)