静态初始化块

问题

据我所知,"静态初始化块"用于设置静态字段的值,如果不能在一行中完成的话。

但我不明白为什么我们需要一个特殊的块。例如,我们将一个字段声明为静态(没有值赋值)。然后编写几行代码,生成并为上面声明的静态字段赋值。

为什么我们需要在一个特殊的块中使用这些行:static {...}


#1 热门回答(362 赞)

然后静态块:

{
    // Do Something...
}

每次构造an类的实例时,都会调用。无论你创建的那种类型的对象有多少,当静态类本身被初始化时,静态块一次被称为****。

例:

public class Test {

    static{
        System.out.println("Static");
    }

    {
        System.out.println("Non-static block");
    }

    public static void main(String[] args) {
        Test t = new Test();
        Test t2 = new Test();
    }
}

这打印:

Static
Non-static block
Non-static block

#2 热门回答(114 赞)

如果它们不在静态初始化块中,它们会在哪里?为了初始化的目的,你如何声明一个仅仅是本地的变量,并将其与字段区分开来?例如,如何写:

public class Foo {
    private static final int widgets;

    static {
        int first = Widgets.getFirstCount();
        int second = Widgets.getSecondCount();
        // Imagine more complex logic here which really used first/second
        widgets = first + second;
    }
}

Iffirstsecond不是一块,它们看起来像是田地。如果它们位于前面没有static的块中,那么它将被视为实例初始化块而不是静态初始化块,因此每个构造实例将执行一次,而不是总共执行一次。

现在在这种特殊情况下,你可以使用静态方法:

public class Foo {
    private static final int widgets = getWidgets();

    static int getWidgets() {
        int first = Widgets.getFirstCount();
        int second = Widgets.getSecondCount();
        // Imagine more complex logic here which really used first/second
        return first + second;
    }
}

...但是当你希望在同一个块中分配多个变量时,这不起作用,或者没有(例如,如果你只想记录某些内容 - 或者可能初始化本机库)。


#3 热门回答(89 赞)

这是一个例子:

private static final HashMap<String, String> MAP = new HashMap<String, String>();
  static {
    MAP.put("banana", "honey");
    MAP.put("peanut butter", "jelly");
    MAP.put("rice", "beans");
  }

"静态"部分中的代码将在类加载时执行,然后构造类的任何实例(并且在从其他地方调用任何静态方法之前)。这样你就可以确保类资源都可以使用了。

也可以使用非静态初始化程序块。这些行为类似于为类定义的构造函数方法的扩展。它们看起来就像静态初始化块一样,除了关闭"static"关键字。