Unfortunately I haven't coded Java for about five years and I absolutely can not remember how or why the following code is working.
I stumbled across a similar example and broke it down to this. The emphasis is on the part below the comment: I don't get the constructor notation followed by the block in double brackets. And unfortunately I can not find anything in the Java documentation or by using Google (what word(s) should I google?).
package syntaxtest;
public class Main {
public static void main(String[] args) {
// What kind of notation is this?
MyTest tester = new MyTest() {{
setName("John Johnson");
}};
System.out.println(tester.getName());
}
}
class MyTest {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
So here are my questions:
- How is this notation/syntax called?
- Where can I read some documentation about it?
I guess/ hope I will be able to answer the second question by myself if somebody can provide me with the answer to the first question.
To make it clear: I know the output is John Johnson
;) But I don't know why it is working.
This is known as double brace initialization:
The first brace creates a new
AnonymousInnerClass, the second
declares an instance initializer block
that is run when the anonymous inner
class is instantiated. This type of
initializer block is formally called
an "instance initializer", because it
is declared within the instance scope
of the class -- "static initializers"
are a related concept where the
keyword static is placed before the
brace that starts the block, and which
is executed at the class level as soon
as the classloader completes loading
the class (specified at
http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.6)
The initializer block can use any
methods, fields and final variables
available in the containing scope, but
one has to be wary of the fact that
initializers are run before
constructors.
This only works only for non-final
classes because it creates an
anonymous subclass.
Let's layout the code a bit differently:
MyTest tester = new MyTest() {
{
setName("John Johnson");
}
};
What you see here is called double brace initialization. You have an anonymous inner subclass of class MyTest
, along with an initializer block, which is a block that contains code that is run when the object is constructed.
Normally, you would put such code in the constructor, but since anonymous inner classes can't have constructors, this is the only way to guarantee the code is run when it's supposed to.
Having said that, it's a bit ugly to do this. There are better ways. However, I do use it myself on occasion, usually in the following idiom to create an immutable map:
final Map<String, Integer> textToInt = Collections.unmodifiableMap(new HashMap<String, Integer>() {{
put("one", 1);
put("two", 2);
// etc
}});
Which creates a new map, overrides it, adds some values to it in the initializer block, and wraps it in an unmodifiable map.
MyTest tester = new MyTest() {{
setName("John Johnson");
}};
is the same as
MyTest tester = new MyTest();
tester.setName("John Johnson");