为什么选择java Instance初始化器?

Java中的“实例初始化器”有什么意义?
我们不能只将那段代码放在构造函数的开头吗?

我经常使用它们,通常用于在一个语句中创建和填充Map(而不是使用丑陋的静态块):

private static final Map CODES = new HashMap() { { put("A", "Alpha"); put("B", "Bravo"); } }; 

一个有趣且有用的装饰是在一个声明中创建一个不可修改的地图:

 private static final Map CODES = Collections.unmodifiableMap(new HashMap() { { put("A", "Alpha"); put("B", "Bravo"); } }); 

比使用静态块更简洁,并处理最终的奇异赋值等。

另一个提示:不要害怕创建简化实例块的方法:

 private static final Map CODES = new HashMap() { { put("Alpha"); put("Bravo"); } void put(String code) { put(code.substring(0, 1), code); } }; 

您确实可以将代码放在每个构造函数的开头。 但是,这正是实例初始化程序的要点:它的代码应用于所有构造函数,如果你有许多构造函数和一些对所有构造函数都通用的代码,这可能很方便。

(如果你刚刚开始编程,你可能不知道可以为同一个类创建许多构造函数(只要它们采用不同的参数);这称为构造函数重载 。如果你只有一个构造函数,然后实例初始化程序确实不是很有用(编辑:除非你在创意时尚中滥用它,如其他答案中所示)。)

您可以在声明匿名类时使用实例初始值设定项,例如,在执行Double Brace Initialization Idiom时 。

 List mylist = new ArrayList(){{add("a"); add("b"); add("c");}}; 

在这里,您可以初始化对象,即使您无法向构造函数添加任何内容(因为该类是匿名的)。

由于这里的所有代码示例都使用匿名类,因此我将这个(稍微可怕的)类放在一起,该类演示了在“适当”类中使用实例初始化器。 您可以使用它们执行复杂处理或在初始化时处理exception。 请注意,这些块在构造函数运行之前运行, 构造函数在子类中的初始化程序运行之前运行:

 import java.util.Scanner; public class InstanceInitializer { int x; { try { System.out.print("Enter a number: "); x = Integer.parseInt(new Scanner(System.in).nextLine()); } catch (NumberFormatException e) { x = 0; } } String y; { System.out.print("Enter a string: "); y = new Scanner(System.in).nextLine(); for(int i = 0; i < 3; i++) y += y; } public InstanceInitializer() { System.out.println("The value of x is "+x); System.out.println("The value of y is "+y); } public static class ChildInstanceInitializer extends InstanceInitializer { { y = "a new value set by the child AFTER construction"; } } public static void main(String[] args){ new InstanceInitializer(); new InstanceInitializer(); System.out.println(); System.out.println(new ChildInstanceInitializer().y); // This is essentially the same as: System.out.println(new InstanceInitializer(){ {y = "a new value set by the child AFTER construction";} }.y); } } 

这输出(类似):

 Enter a number: 1 Enter a string: a The value of x is 1 The value of y is aaaaaaaa Enter a number: q Enter a string: r The value of x is 0 The value of y is rrrrrrrr Enter a number: 3 Enter a string: b The value of x is 3 The value of y is bbbbbbbb a new value set by the child AFTER construction Enter a number: s Enter a string: Hello The value of x is 0 The value of y is HelloHelloHelloHelloHelloHelloHelloHello a new value set by the child AFTER construction 

请注意,直到已经调用父类的构造函数之后才会设置“新值”字符串。