这个构造函数调用以下双括号是什么?

时间:2009-07-08 19:36:51

标签: java syntax constructor anonymous-class

不幸的是,我已经编写了大约五年的Java代码,而且我完全不记得以下代码是如何工作的原因。

我偶然发现了一个类似的例子并将其分解为此。重点是注释下面的部分:我没有得到构造函数符号,后面是双括号中的块。不幸的是,我无法在Java文档中找到任何内容或使用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;
    }
}

所以这是我的问题:

  1. 如何调用此符号/语法?
  2. 我在哪里可以阅读有关它的文档?
  3. 我想/希望如果有人能够为我提供第一个问题的答案,我将能够自己回答第二个问题。

    说清楚:我知道输出是John Johnson;)但我不知道它为什么会起作用。

3 个答案:

答案 0 :(得分:21)

这称为double brace initialization

  

第一个大括号创造了一个新的   AnonymousInnerClass,第二个   声明一个实例初始化块   那是在匿名内心时运行的   class被实例化。这类   初始化块正式调用   一个“实例初始化器”,因为它   在实例范围内声明   该类 - “静态初始化器”   是一个相关的概念   关键字static放在之前   支撑开始阻止,哪个   很快就会在班级执行   当类加载器完成加载   班级(指定于   http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.6)   初始化块可以使用任何   方法,字段和最终变量   在包含范围内可用,但是   一个人必须警惕这个事实   初始化器之前运行   构造

     

这仅适用于非最终版   类因为它创建了一个   匿名子类。

答案 1 :(得分:15)

让我们以不同的方式布局代码:

MyTest tester = new MyTest() {
  {
    setName("John Johnson");
  }
};

您在此处看到的内容称为双括号初始化。你有一个类MyTest的匿名内部子类,以及一个初始化块,它是一个包含在构造对象时运行的代码的块。

通常,您会将这些代码放在构造函数中,但由于匿名内部类不能有构造函数,因此这是保证代码运行的唯一方法。

话虽如此,这样做有点难看。有更好的方法。但是,我偶尔会自己使用它,通常用下面的习惯用法创建一个不可变的地图:

final Map<String, Integer> textToInt = Collections.unmodifiableMap(new HashMap<String, Integer>() {{
    put("one", 1);
    put("two", 2);
    // etc
}});

创建新地图,覆盖它,在初始化程序块中为其添加一些值,并将其包装在不可修改的地图中。

答案 2 :(得分:-5)

MyTest tester = new MyTest() {{
   setName("John Johnson");
}};

相同
MyTest tester = new MyTest();
tester.setName("John Johnson");