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

时间:2011-07-20 14:29:57

标签: java

Java中“实例初始化器”的含义是什么? 我们不能把这段代码放在构造函数的开头吗?

4 个答案:

答案 0 :(得分:38)

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

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

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

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

比使用静态块更简洁,并处理单个赋值给最终等。

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

private static final Map<String, String> CODES = new HashMap<String, String>() {
    {
        put("Alpha");
        put("Bravo");
    }

    void put(String code) {
        put(code.substring(0, 1), code);
    }
};

答案 1 :(得分:24)

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

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

答案 2 :(得分:7)

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

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

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

答案 3 :(得分:5)

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

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

请注意,在父类的构造函数被调用之后才会设置“new value”字符串。