2009-07-08 58 views
14

不幸的是,我已经将Java编码了大约五年了,而且我完全记不起以下代码的工作原理。这是什么构造函数调用以下双括号?

我偶然发现了一个类似的例子,并将其分解为这个。重点是评论下面的部分:我没有得到构造函数表示法,后面跟着括号中的块。不幸的是,我无法在Java文档或使用Google中找到任何内容(我应该使用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. 我可以在哪里阅读关于它的一些文档?

我想/希望如果有人能为我提供第一个问题的答案,我将能够自己回答第二个问题。

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

+0

当我第一次看到它在Usenet我不得不看它一会儿意识到发生了什么事了。一旦你知道它是什么,这是显而易见的。 – 2009-07-08 19:43:38

+0

前段时间我看到了这个巧妙的技巧,但我也看到了很多免责声明,说很容易打破它的东西/不是很可靠。如果我要尝试使用它,我一定会考虑到A)我必须向每个人解释它,以便从那时起查看代码,并且B)我必须做一些研究了解使用这种模式的所有含义。 – 2009-07-08 20:20:53

回答

20

这被称为double brace initialization

第一支杆创建一个新的 AnonymousInnerClass,第二 声明了一个实例初始化块 当匿名内部 类被实例化时运行。这种类型的 初始化块的正式的称呼 的“实例初始化”,因为它是 实例范围类的 内声明的 - “静态初始化” 是一个相关的概念,在这里 关键字static是 前放置撑启动该块,并且其 作为所述类装入器完成加载 类(在 http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.6指定) 的初始化代码块可以使用任何 方法,字段和最后变量 在可用在类级尽快执行 包含范围,但必须是 警惕 构造函数在 构造函数之前运行。

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

14

让我们布局的代码有点不同:

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 
}}); 

这将创建一个新的地图,覆盖它,增加了一些价值给它的初始化块,并把它封装在一张不可修改的地图中。

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

相同

MyTest tester = new MyTest(); 
tester.setName("John Johnson"); 
相关问题