public class Test {
public static final Person p;
static {
p = new Person();
p.setName("Josh");
}
}
和
public class Test {
public static final Person p = initPerson();
private static Person initPerson() {
Person p = new Person();
p.setName("Josh");
return p;
}
}
我一直使用第二个,但静态初始化块有什么不同吗?
答案 0 :(得分:7)
当然存在技术差异(你可以在你的课程中多次调用静态方法,你可以通过反射调用它等)但是,假设你没有做任何这种诡计,你和#39;对 - 这两种方法实际上完全相同。
我也更喜欢基于方法的方法,因为它为代码块提供了一个很好的名称。但它几乎完全是一种风格方法。
正如Marko所指出的,基于方法的方法还用于分离创建Person的两个问题,并将其分配给静态变量。使用静态块,这两个东西被组合在一起,如果块是非平凡的,则会损害可读性。但是使用方法方法,该方法仅负责 来创建对象,并且静态变量的初始化仅负责 以采用该方法结果并将其分配给变量。
更进一步说明:如果我有两个静态字段,一个依赖于另一个,那么我将声明两个方法,并让第二个方法将第一个变量作为显式参数。我喜欢保持我的静态初始化方法完全没有状态,这使得更容易推断出应该发生哪一个(以及它假定已经创建了哪些变量)。
所以,比如:
public class Test {
public static final Person p = initPerson();
public static final String pAddress = lookupAddress(p);
/* implementations of initPerson and lookupAddress omitted */
}
从这一点可以看出,(a)您不需要pAddress
来初始化p
,以及(b)您做需要p
来初始化lookupAddress
。事实上,如果你以相反的顺序尝试它们而你的静态字段是非final
,编译器会给你一个编译错误("非法前向引用"):
public static String pAddress = lookupAddress(p); // ERROR
public static Person p = initPerson();
使用静态块会丢失清晰度和安全性。编译得很好:
static {
pAddress = p.findAddressSomehow();
p = new Person();
}
...但它在运行时失败,因为在p.findAddressSomehow()
,p
的默认值为null
。
答案 1 :(得分:3)
每次调用时都会执行静态方法(第二个示例)。静态初始化块(第一个示例)仅在初始化类时调用一次。
http://docs.oracle.com/javase/tutorial/java/javaOO/initial.html
私有静态方法的优点是,如果需要重新初始化类变量,它们可以在以后重用。
这不计入final
个实例,因为最终变量只能初始化一次。
答案 2 :(得分:1)
initPerson需要在某个时刻调用,而静态块在创建Test对象时执行。
答案 3 :(得分:1)
函数之前的静态指定您可以通过在类名称句柄本身上调用它来使用该函数。例如,如果要在类外创建Person对象,可以编写
Person p = Test.initPerson();
然而,两者之间没有任何有利的区别,因为在两种情况下都可以访问类外的对象p。