3

In Java I can do this:

    enum Color {RED, BLUE, GREEN };
    enum Weight {LIGHT, HEAVY }

    Enum e = Color.RED;
    assertEquals(Color.RED, e);
    e = Weight.HEAVY;
    assertEquals(Weight.HEAVY, e);

I can put the enum in a Map and that still works:

    Map<String, Enum> map = Maps.newHashMap();
    map.put("color", Color.RED);
    map.put("weight", Weight.HEAVY);
    assertEquals(Color.RED, map.get("color"));
    assertEquals(Weight.HEAVY, map.get("weight"));

However, I am not able to do the same with collections of enums.

   List<Enum> enumList = new ArrayList<Color>();  //error

Is that not allowed in Java or am I just doing it wrong?

Is there a better way to maintain a mapping of properties to Enums that represent them?

naumcho
  • 18,671
  • 14
  • 48
  • 59
  • 3
    You are doing different things in your `Map` example vs your `List` example. Do you see that? (The type arguments, inferred and provided.) – Sotirios Delimanolis Jun 26 '14 at 20:56
  • 1
    Also, don't use raw types. – Sotirios Delimanolis Jun 26 '14 at 20:59
  • The "List is not a subtype of List" seems to be what I was missing here. So how can I generically store different collections of Enums then? – naumcho Jun 26 '14 at 21:08
  • See http://stackoverflow.com/questions/9810445/listmapstring-string-vs-list-extends-mapstring-string – Eng.Fouad Jun 26 '14 at 21:10
  • Why do you want to have a list of enums without knowing what kind of enums they are e.g., whether they are colors, weights, or something else? What possible use could this serve? – David Conrad Jun 26 '14 at 21:14
  • I am writing a library that will work with user Enums and pass them around and call Callable's on them etc so I don't really care what the enum type is - the user will give me a Callable that will evaluate it, but I do need to be able to take any type of enum generically – naumcho Jun 26 '14 at 21:22

6 Answers6

2

The type argument to your list appears to be incorrect,

List<Enum> enumList = new ArrayList<Color>();

Should probably be

List<Enum> enumList = new ArrayList<Enum>();

or (use the diamond operator - Java 7 and up with)

List<Enum> enumList = new ArrayList<>();
Community
  • 1
  • 1
Elliott Frisch
  • 198,278
  • 20
  • 158
  • 249
2
List<? extends Enum> enumList = new ArrayList<Color>();

Color is subtype of an Enum but List<Color> is not subtype of List<Enum>.

You have to explicitly say "List of something that is subetype of Enum" which in Java is:

List<? extends Enum>

damienix
  • 6,463
  • 1
  • 23
  • 30
2

ArrayList will always function as a List. Color will always function as an Enum.

However: ArrayList<Color> will not always function as a List<Enum>.

Example:

    List<Enum> EvilList = new ArrayList<Color>();
    EvilList.add(Some other Enum);
    // Because EvilList is, in its definition, a List<Enum>, allowing your code to
    // compile would break the type safety that generics are meant to preserve.

Note, however, that List<Color> would not break generic type safety.

Sebastian
  • 108
  • 1
  • 9
2

You have to use wildcards for that kind of assignment:

List<? extends Enum> enumList = new ArrayList<Color>();

Wildcards allow that kind of assignment, though you cant do certain things on the collection.. such as adding elements that extends Enum (since you wouldnt know the type referenced object). You can only get elements from Enum and up.

If you want to be able to keep adding elements, make the array list like this:

ArrayList<Enum>
Ed Morales
  • 1,027
  • 5
  • 9
2

Enum is a generic class so give it it's generic parameter:

List<Enum<Colour>> l = new ArrayList<Enum<Colour>>();

which can be shortened to:

List<Colour> l = new ArrayList<Colour>();

the following is valid code:

    List<Enum<Colour>> ecl = new ArrayList<Enum<Colour>>();
    List<Colour> cl = new ArrayList<Colour>();
    ecl.add(Colour.Blue);
    cl.add(Colour.Blue);
OldCurmudgeon
  • 64,482
  • 16
  • 119
  • 213
0

If there is only 1 value per enum to store:

Map<Class<? extends Enum>, Enum<?>> map = new HashMap<Class<? extends Enum>, Enum<?>>();
map.put(Color.class, Color.BLUE);
map.put(Weight.class, Weight.LIGHT);
Color color = getFromMap(map, Color.class);

private static <T> T getFromMap(Map<Class<? extends Enum>, Enum<?>> map, Class<T> itemClass) {
    return (T) map.get(itemClass);
}

otherwise

List<Enum<?>> list = new ArrayList<Enum<?>>();
list.add(Color.BLUE);
list.add(Weight.LIGHT);
Color fromList = getFromList(list, 1, Color.class);

private static <T> T getFromList(List<Enum<?>> list, int i, Class<Color> outType) {
    return (T) list.get(i);
}
damienix
  • 6,463
  • 1
  • 23
  • 30