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

时间:2012-08-08 17:29:23

标签: java

  

可能重复:
  How is an instance initializer different from a constructor?

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

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

2 个答案:

答案 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);
}

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