以下代码中的{{ ... }}
块是什么意思?
class X {
private Y var1;
private X() {
Z context = new Z(new SystemThreadPool()) {{
var1 = new Y();
}};
}
}
以下代码中的{{ ... }}
块是什么意思?
class X {
private Y var1;
private X() {
Z context = new Z(new SystemThreadPool()) {{
var1 = new Y();
}};
}
}
它意味着您正在创建一个匿名子类,双括号内的代码基本上是一个构造函数。它经常用于向集合中添加内容,因为Java的语法实际上是集合常量的创建方式有些笨拙。
所以你可能会这样做:
List<String> list = new ArrayList<String>() {{
add("one");
add("two");
add("three");
}};
而不是:
List<String> list = new ArrayList<String>();
list.add("one");
list.add("two");
list.add("three");
我实际上不喜欢那样,更喜欢这样做:
List<String> list = Arrays.asList("one", "two", "three");
因此,在这种情况下,这并没有太多意义,而对于例如地图这样没有方便的帮助程序的东西来说,则有意义。
“外部”大括号表示你正在创建一个匿名子类,第二对大括号是对象初始化器。初始化器在类的构造函数之前运行,但在任何super
调用之后(因此也在任何超类初始化器之后)。您还可以在非匿名类中使用初始化器,这是一种方便的方法来初始化final
字段,如果您有多个不能相互调用的构造函数或需要比通常的字段初始化器更复杂的初始化的字段。
考虑下面这个类:
class X extends Y{
private final int lulz;
private static boolean someCondition(){...}
private static boolean danger() throws SomeException { ... }
public X(A a) throws SomeException {
super(a);
lulz = someCondition()? danger() : 0;
}
public X(B b) throws SomeException {
super(b);
lulz = someCondition()? danger() : 0;
}
}
它可以重写为:
class X extends Y{
private final int lulz;
private static boolean someCondition(){...}
private static boolean danger() throws SomeException { ... }
{ // initalizer -- might throw SomeException!
lulz = someCondition()? danger() : 0;
}
public X(A a) throws SomeException { super(a); }
public X(B b) throws SomeException { super(b); }
}
如果初始化程序可能会抛出受检异常,所有的构造函数都必须声明它们可以抛出该异常。
anonymous class 和class Instance initializer idiom。
class X {
private Y var1;
private X() {
Z context = new Z(
new SystemThreadPool()) {
{ // This is the initialize idiom
var1 = new Y(); //
} //
}
); // BTW you are missing ")"
}
}
如之前的答案所提到的,双大括号初始化是正确的。
它使用了一种特殊的技术来在Java中初始化实例成员。这是一种简写方式,用于在类定义中定义一个共享的代码块,当任何一个类构造函数被激活时都会运行。
我添加了官方Java文档的链接,以便更全面地了解该主题。
从文档中:
Initializer blocks for instance variables look just like static initializer blocks, but without the static keyword:
{
// whatever code is needed for initialization goes here
}
The Java compiler copies initializer blocks into every constructor. Therefore, this approach can be used to share a block of code between multiple constructors.