不幸的是,我已经编写了大约五年的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;
}
}
所以这是我的问题:
我想/希望如果有人能够为我提供第一个问题的答案,我将能够自己回答第二个问题。
说清楚:我知道输出是John Johnson
;)但我不知道它为什么会起作用。
答案 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");