0

We have a habit of constructing EnumMap<K,V> instances like in the following EnumMapExample.java example:

package test;

import java.util.EnumMap;

public class EnumMapExample {

    enum TestEnum {SOME_VALUE, SOME_OTHER_VALUE}

    private final EnumMap<TestEnum, String> myEnumMap = new EnumMap<TestEnum, String>(TestEnum.class) {
        {
            // How is this construct called?
            put(TestEnum.SOME_VALUE, "someValue");
            put(TestEnum.SOME_OTHER_VALUE, "someOtherValue");
        }
    };

    public void printMyEnumMap() {
        for (final TestEnum key : myEnumMap.keySet()) {
            final String value = myEnumMap.get(key);
            System.out.println("myEnumMap key: " + key + " has value " + value);
        }
    }

    public static void main(final String[] args) {
        new EnumMapExample().printMyEnumMap();
    }
}

Likely a question with a quick answer, but I can't for the Google of me find how this way of filling the private final EnumMap<TestEnum, String> myEnumMap with the 2 (contrived) enum types is called and how it works?

Question refinement: So I'm calling new EnumMap<K,V>(SomeEnum.class){{ /* initialization code */ }}; Note the double curly braces {{ }} before the semicolon ;. What's that double braces thing?

drvdijk
  • 5,556
  • 2
  • 29
  • 48

2 Answers2

1

Edit: Just realized that you might have been looking to do double brace initialization.

Double brace initialization works by creating an anonymous subclass of the original class and using an initialization block to alter the class. So the code sort of works as such:

static final EnumMapAnonSubclass<TestEnum, String> extends EnumMap<TestEnum, String> { // outer braces
    { // inner braces
    put(TestEnum.SOME_VALUE, "someValue");
    put(TestEnum.SOME_OTHER_VALUE, "someOtherValue");
    }
    // Implicitly created constructor
    EnumMapAnonSubclass(Class<? extends TestEnum> clazz) {
        super(clazz);
    }
};

private final EnumMap myEnumMap = new EnumMapAnonSubclass(TestEnum.class)

If you just want to create the EnumMap, you already have everything you needed.

private final EnumMap<TestEnum, String> myEnumMap = new EnumMap<TestEnum, String>(TestEnum.class);

is all you needed to create the map.

If you want to initialize the map with some values at object creation, you can use an initialization block (http://docs.oracle.com/javase/tutorial/java/javaOO/initial.html) or a method that is called in the constructor of the object.

So if you wanted to both create the map and stick stuff in it, your code would look something like this:

// Create the EnumMap
private final EnumMap<TestEnum, String> myEnumMap = new EnumMap<TestEnum, String>(TestEnum.class);
// Use an initialization block to put some values in it when an instance of EnumMapExample is created
{
    put(TestEnum.SOME_VALUE, "someValue");
    put(TestEnum.SOME_OTHER_VALUE, "someOtherValue");
}
awksp
  • 11,764
  • 4
  • 37
  • 44
  • Thanks for that link, the term "Initializer block" is likely what I am looking for. Creating the `EnumMap` is not the problem, I'm just wondering about the initialization block that adds the values to the (then already created) map. Follow-up question on your answer though: I'm calling `new EnumMap(SomeEnum.class){{ /* initialization code */ }}`. Note the double curly braces `{{ }}` before the semicolon `;`. What's that double braces thing? – drvdijk Apr 30 '14 at 03:06
  • Also, for future reference this is called "double-brace initialization". I'm not sure how widely used it is, or how wise it is to try to use it, but it's an interesting little corner of Java – awksp Apr 30 '14 at 03:16
  • Well that comment really was the answer to my question, "double-brace initialization" :-) Thanks! – drvdijk Apr 30 '14 at 13:11
1

This is equivalent to following construct

static class MyEnumMap extends EnumMap<TestEnum, String> {

    // initialization block
    {
        put(TestEnum.SOME_VALUE, "someValue");
        put(TestEnum.SOME_OTHER_VALUE, "someOtherValue");
    }

    public MyEnumMap(Class<TestEnum> keyType) {
        super(keyType);
    }

}

private final EnumMap<TestEnum, String> myEnumMap = new MyEnumMap(TestEnum.class);

so entries are added to MyEnumMap instance in the process of its initialization

Evgeniy Dorofeev
  • 133,369
  • 30
  • 199
  • 275
  • Thanks for this explanation. I did accept the other answer though because that names the construct as "double brace initialization", the term I was looking for. Which of the implicit constructor signatures is 'more' correct? `public MyEnumMap(Class keyType)` or `MyEnumMap(Class extends TestEnum> keyType)` – drvdijk Apr 30 '14 at 13:32