javaenum-map

Java EnumMap Parameter confusion


I'm working with an EnumMap for the first time, and don't understand what the parameter pass is actually doing. As far as I can tell it's just "K.class" where K is the map key. This works just fine, but I haven't seen this anywhere else in Java and I'm not clear on what role it's actually playing in the construction.

I guess this is a theoretical question because the code runs: what does the "K.class" parameter mean, and what does the EnumMap need it for?


Solution

  • See the linked question for class literals.

    EnumMap specifically needs it, because it needs to know how many different values the enum has. This is because EnumMap is a highly optimized map implementation for enums that uses only one array with one slot for every possible value (instead of a much larger array like a HashMap). When you call get(), it retrieves the index of the given key (i.e., the first enum value, the second etc.) and looks in the appropriate position of its internal array. For this the constructor needs to know the number of possible values to allocate an array of the correct size. Given the class object, it can call getEnumConstants() to find out the number of existing values for this enum.

    Furthermore, imagine the following code:

    enum Enum1 { V1, V2; }
    enum Enum2 { W1, W2; }
    EnumMap<Enum1, Object> map = new EnumMap<Enum1, Object>(Enum1.class);
    map.put(Enum1.V1, new Object());
    map.get(Enum2.W1);
    

    Now the get method should obviously return null. However, as I said, the map internally has only one array, in this case of size 2, with the new object in the first slot and null in the second. It did not store a reference to Enum1.V1 when you passed it to put(). However, the method get now needs to know that the passed value does not belong to the correct enum, and thus there is no value for this key in the map. Here too it needs the type of the correct enum, and for this you need to pass the type to the constructor.

    Without you giving some information about the enum to the constructor, it would not know which enum you intent to use with this map instance. Even if you write new EnumMap<MyEnum, SomeValue>(), the constructor cannot know about the value MyEnum of the generic type parameter due to type erasure. Thus there needs to be another way to pass the information to the constructor.