为什么使用静态块直接初始化实例变量?

时间:2012-01-29 21:18:53

标签: java

为什么我会使用静态块:

static {
   B = 10;
}

在:

Integer B = 10;

一方的优势/劣势是什么?

5 个答案:

答案 0 :(得分:13)

static块允许您为属性编写更复杂的初始化逻辑,而单行初始化将您限制为单个表达式。

请注意,实例和静态属性都存在初始化块,例如,这个初始化块在实例化时初始化实例属性:

private int a;
{ a = 10; }

然而,这个在类加载时初始化静态属性:

private static int b;
static { b = 10; }

初始化过程在here中作为JVM规范的一部分进行了详细说明。

答案 1 :(得分:10)

只在必要时才应使用静态初始化程序块。例如,有时您需要执行几个步骤来计算字段的最终值。在这种情况下,您有两个机会:编写一个计算值的方法并将您的字段声明为static final Integer B = calculateB(),或使用初始化程序块:

static final Integer B;
static {
  int temp = ...;
  ...
  B = temp;
}

在这种情况下,我更喜欢静态块,因为方法可能会令人困惑(其他开发人员可能会尝试调用它,尽管它只是在初始化期间调用一次)。

同样适用于实例字段,尽管通常可以避免不寻常的初始化块,只需将字段的初始化逻辑写入构造函数(当然,静态字段不可能)。

答案 2 :(得分:4)

加载类时会发生静态初始化。

E.g。它将是一个初始化成员变量的适当位置,否则由于多个线程的访问而需要同步。

如果你明确地调用构造函数,第二种情况就会发生。

用法不同。
例如。你更喜欢延迟加载某些东西的第二种情况(如果你把它放在静态初始化器中它总是加载,也许你不想要那个 - 更喜欢延迟加载它)

答案 3 :(得分:3)

首先,您的Integer B似乎是非静态成员变量,无法从静态块访问。所以要么你想要写

//Initialize static field
static {
   B = 10;
}
static Integer B = 10;

//Initialize member field
{
   B = 10;
}
Integer B = 10;

在这两种情况下,您都可以使用它来初始化B,其值可能会导致异常或执行更复杂的操作而无需为init编写特殊方法。

{
   try{
      B = thisWillThrowAFileNotFound();
   }catch(FileNotFoundException){
      B = 10;//Set default
   }

}

答案 4 :(得分:2)

实际上,如果你有

private static Integer B = 10;

编译器将转换为,基本上:

private static Integer B;
static {
    B = 10;
}

使用静态块的是你可以使用整个语言而不仅仅是表达式来进行初始化。想象一下,你需要一个具有7的倍数的数组。你可以这样做:

private static Integer[] array;
static {
    array = new Integer[1000];
    for (int i = 0; i < 1000; i++) {
        array[i] = 7 * i;
    }
}

无论如何,你也可以这样做:

private static Integer[] array = initArray();
private static Integer[] initArray() {
    Integer[] result = new Integer[1000];
    for (int i = 0; i < 1000; i++) {
        result[i] = 7 * i;
    }
    return result;
}