Anonymous/Local/Inner class gotchas

If it isn’t defined as static then it implicitly keeps a reference to it’s outer instance. One issues is memory leaks due to entanglement.

JLS §8.6: Instance Initializers

This will create a special class for ‘bar’ and bar holds a reference to it’s container.


  @SuppressWarnings("serial")
  HashMap<String,String> bar = new HashMap<String, String>() {{
    put("foo", "xyzzy");
    put("bar", "yzzyx");
  }};

which can be trivially reworked to this (without an anonymous class):


  HashMap<String,String> bar = new HashMap<>();
  {
    bar.put("foo", "xyzzy");
    bar.put("bar", "yzzyx");
  }

There’s still a style gotcha here in that this is using an instance initializer and if ‘bar’ was changed to static the code would be executed each time a new instance of the container is created. The initializer would also have to be changed to a static one.

Why would anyone do that :confused:

Ah, the eternal question. I’d guess because it’s less typing. I threw this together 'cause I saw it a couple of times…not too crazy if ‘bar’ was static. You still have an extra class for the anonymous type.

(EDIT: foo -> bar)

^ :point: I don’t know
A new class creates more overhead than a new instance of an existing class. The new class, even if it is an anonymous one, has to be loaded, linked, and initialized: JLS 12.3 - 12.4 Linking and Initialization of Classes and Interfaces.
This adds memory and processing overhead for a savings of 2 or 3 keystrokes.
Plus, when the code runs multiple times, each execution creates not one object, but 2 adding a non trivial amount of overhead if the code is in a method that runs frequently.

I ain’t advocating this, but: true about loading-linking-initialization, but the number of instances remains the same…just the anon references the container which is the much bigger (IMO) concern.

(EDIT: Added a non-anon version which is more sane)