在java中使用非静态块有什么用?

可能重复:
实例初始值设定项与构造函数有何不同?

当所有必需的工作都可以在构造函数内完成时,为什么我们仍然需要Java中的非静态块?

编辑:在构造函数之前每次运行非静态块的普通类怎么办?

除了@ Bohemian的回答。

如果您有多个构造函数,则一个intialiser块可以避免重复。

public class A { final Map map = new HashMap(); { // 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 

您可以将它与匿名类一起使用:

 new MyClass() { { // do something extra on construction (after the constructor executes) } } 

我发现这对于初始化“查找”地图(即固定内容)特别有用:

 Map map = new HashMap() { { put("foo", "bar"); put("one", "two"); // etc } }; 

仅供参考,这有时(很差)称为“双支撑初始化”,实际上它只是采用初始化块

虽然这样一个匿名类在技术上是一个子类 ,但是在使用这种技术与创建不可修改的映射时更传统的技术进行比较时,会显示出它的美妙之处:

比较这个直接的单行,将数据和赋值放在一起:

 private static final Map map = Collections.unmodifiableMap( new HashMap() {{ put("foo", "bar"); put("one", "two"); // etc }}); 

有了这个混乱,由于final只允许一个赋值,它必须创建一个单独的对象:

 private static final Map map; static { Map tempMap = new HashMap(); tempMap.put("foo", "bar"); tempMap.put("one", "two"); // etc map = Collections.unmodifiableMap(tempMap); } 

另请注意,对于混乱版本,这两个语句不必相邻,因此不可修改的映射的内容变得不那么明显。