6

Recently, I stumbled upon the following java syntax:

ArrayList<String> nodes = new ArrayList<String>(){{add("n1");add("n2");}};

At first, I thought that it is a syntax error, but to my surprise, the code gave no compilation or runtime error.

I have the following questions:

  • Is there a standard definition and documentation for such declaration in Java?
  • What happens when this code is compiled?

Please point me towards relevant literature.

Bhoot
  • 2,614
  • 1
  • 19
  • 36

2 Answers2

2

This creates an anonymous class with a custom initializer (see Initializing Instance Members):

Normally, you would put code to initialize an instance variable in a constructor. There are two alternatives to using a constructor to initialize instance variables: initializer blocks and final methods. Initializer blocks for instance variables look just like static initializer blocks, but without the static keyword:

{
    // whatever code is needed for initialization goes here
}

It's convient when you want a list with members already in it, but produces more code when compiled because the anonymous class is actually compiled to a (global) class different that extends ArrayList.

I've recently read this post which is relevant to the matter:

The first point to note is that the Java runtime has no understanding of inner classes at all. Whether the inner class is named or anonymous, a smoke-and-mirrors procedure is used to convert the inner class to a global class. If the class has a name, then the compiler generates class files whose names have the format [outer]$[inner] — $ is a legal identifier in Java. For inner classes, the generated class files are simply numbered. So when the Thread example at the start of this article is compiled, we end up with a class file called Test$1.class. The number '1' indicates that this is the first anonymous class defined within the class Test.

Reut Sharabani
  • 30,449
  • 6
  • 70
  • 88
0

It's an instance block, which is executed on construction, of an anonymous subclass.

Unless there's a good reason, don't do this. Prefer:

List<String> nodes = Arrays.asList("n1", "n2");

Or if you need mutability:

List<String> nodes = new ArrayList(Arrays.asList("n1", "n2"));

Because the anonymous class keeps a reference to the containing instance of the class it's declared in, which can lead to memory leaks.

Bohemian
  • 412,405
  • 93
  • 575
  • 722