可能重复:
How is an instance initializer different from a constructor?
当构造函数内部完成所有必需的工作时,为什么我们仍然需要Java中的非静态块?
编辑:在构造函数之前每次运行非静态块的普通类怎么办?
答案 0 :(得分:13)
除了@ Bohemian的回答。
如果你有多个构造函数,则一个intialiser块可以避免重复。
public class A {
final Map<String, String> map = new HashMap<String, String>(); {
// put things in map.
}
final int number; {
int number;
try {
number = throwsAnException();
} catch (Exception e) {
number = 5;
}
this.number = number;
}
public A() { /* constructor 1 */ }
public A(int i) { /* constructor 2 */ }
}
在构造函数之前每次运行非静态块的普通类怎么办?
技术上,订单是
实际上,所有这些代码都在每个构造函数的字节代码中,因此在运行时构造函数之前或之后都没有。
在对初始化顺序有任何疑惑之前
public class Main extends SuperClass {
{
System.out.println("Initialiser block before constructor");
}
Main() {
System.out.println("Main constructor");
}
{
System.out.println("Initialiser block after constructor");
}
public static void main(String... args) {
new Main() {{
System.out.println("Anonymous initalizer block");
}};
}
}
class SuperClass {
SuperClass() {
System.out.println("SuperClass constructor");
}
}
打印
SuperClass constructor
Initialiser block before constructor
Initialiser block after constructor
Main constructor
Anonymous initalizer block
答案 1 :(得分:7)
您可以将它与匿名类一起使用:
new MyClass() {
{
// do something extra on construction (after the constructor executes)
}
}
我发现这对于初始化“查找”地图(即固定内容)特别有用:
Map<String, String> map = new HashMap<String, String>() {
{
put("foo", "bar");
put("one", "two");
// etc
}
};
仅供参考,这有时(很差)称为“双支撑初始化”,实际上它只是使用initializer block。
虽然这样的匿名类在技术上是子类,但在创建unmodifiable地图时使用此技术与更传统的技术进行比较时,会显示出这种美感:
比较这个简单的单行,将数据和作业放在一起:
private static final Map<String, String> map = Collections.unmodifiableMap(
new HashMap<String, String>() {{
put("foo", "bar");
put("one", "two");
// etc
}});
有了这个混乱,由于final
只允许一个赋值,它必须创建一个单独的对象:
private static final Map<String, String> map;
static {
Map<String, String> tempMap = new HashMap<String, String>();
tempMap.put("foo", "bar");
tempMap.put("one", "two");
// etc
map = Collections.unmodifiableMap(tempMap);
}
另请注意,对于混乱版本,两个语句不必相邻,因此不可修改的映射的内容可能变得不那么明显。