你能解释一下我之间的区别是什么:
public class Test {
public static final Person p;
static {
p = new Person();
p.setName("Josh");
}
}
Run Code Online (Sandbox Code Playgroud)
和
public class Test {
public static final Person p = initPerson();
private static Person initPerson() {
Person p = new Person();
p.setName("Josh");
return p;
}
}
Run Code Online (Sandbox Code Playgroud)
我一直使用第二个,但静态初始化块有什么区别吗?
当然有技术差异(你可以在你的课程中多次调用静态方法,你可以通过反射调用它等)但是,假设你没有做任何这样的诡计,你是对的 - 这两种方法实际上完全相同.
我也更喜欢基于方法的方法,因为它为代码块提供了一个很好的名称.但它几乎完全是一种风格方法.
正如Marko所指出的那样,基于方法的方法还用于分离创建Person的两个问题,并将其分配给静态变量.使用静态块,这两个东西被组合在一起,如果块是非平凡的,则会损害可读性.但该方法的方法,该方法负责单独创建对象,和静态变量的initializion负责仅仅采取这种方法的结果,并将其分配给变量.
更进一步:如果我有两个静态字段,一个依赖于另一个,那么我将声明两个方法,并让第二个方法将第一个变量作为显式参数.我喜欢保持我的静态初始化方法完全没有状态,这使得更容易推断出应该发生哪一个(以及它假定已经创建了哪些变量).
所以,像:
public class Test {
public static final Person p = initPerson();
public static final String pAddress = lookupAddress(p);
/* implementations of initPerson and lookupAddress omitted */
}
Run Code Online (Sandbox Code Playgroud)
这是从看说的很清楚,即(一)你不需要pAddress初始化p,以及(b)你就需要p进行初始化lookupAddress.实际上,如果您以相反的顺序尝试它们并且您的静态字段是非编译器,编译器会给您一个编译错误("非法转发引用")final:
public static String pAddress = lookupAddress(p); // ERROR
public static Person p = initPerson();
Run Code Online (Sandbox Code Playgroud)
使用静态块会丢失清晰度和安全性.编译得很好:
static {
pAddress = p.findAddressSomehow();
p = new Person();
}
Run Code Online (Sandbox Code Playgroud)
......但它会失败在运行时,因为在p.findAddressSomehow(),p 有它的默认值null.