通常,请勿使用非静态初始化器块(也可能避免使用静态初始化器块)。
令人困惑的语法
看着这个问题,有3个答案,但是您用这种语法欺骗了4个人。我就是其中之一,并且我从事Java已有16年了!显然,语法可能容易出错!我会远离它。
伸缩式构造器
对于非常简单的内容,可以使用“ telescoping”构造函数来避免这种混淆:
public class Test {
private String something;
// Default constructor does some things
public Test() { doStuff(); }
// Other constructors call the default constructor
public Test(String s) {
this(); // Call default constructor
something = s;
}
}
建造者模式
如果需要在每个构造函数或其他复杂的初始化末尾执行doStuff(),则也许最好使用构建器模式。 乔什·布洛赫(Josh Bloch)列出了为什么建造者是一个好主意的几个原因。建设者花了一些时间来编写,但是编写得当,使用起来很愉快。
public class Test {
// Value can be final (immutable)
private final String something;
// Private constructor.
private Test(String s) { something = s; }
// Static method to get a builder
public static Builder builder() { return new Builder(); }
// builder class accumulates values until a valid Test object can be created.
private static class Builder {
private String tempSomething;
public Builder something(String s) {
tempSomething = s;
return this;
}
// This is our factory method for a Test class.
public Test build() {
Test t = new Test(tempSomething);
// Here we do your extra initialization after the
// Test class has been created.
doStuff();
// Return a valid, potentially immutable Test object.
return t;
}
}
}
// Now you can call:
Test t = Test.builder()
.setString("Utini!")
.build();
静态初始化循环
我以前用静态初始化程序,但是偶尔会遇到循环,其中两个类在完全加载类之前依赖于彼此的静态初始化程序块被调用。这产生了“无法加载类”或类似的模糊错误消息。我必须将文件与源代码管理中的最新已知工作版本进行比较,以便找出问题所在。一点都没有乐趣。
延迟初始化
也许静态初始化程序在工作时出于性能方面的考虑是好的,并且不太令人困惑。但是总的来说,这些天我更喜欢惰性初始化而不是静态初始化。很明显,它们是做什么的,我还没有遇到与它们一起加载类的错误,并且它们在初始化情况下的工作比初始化程序块要多。
资料定义
现在,我使用Paguro的不可变数据定义帮助器函数来代替用于构建数据结构的静态初始化(与其他答案中的示例进行比较):
private ImMap<String,String> days =
map(tup("mon", "monday"),
tup("tue", "tuesday"),
tup("wed", "wednesday"),
tup("thu", "thursday"),
tup("fri", "friday"),
tup("sat", "saturday"),
tup("sun", "sunday"));
混乱
在Java刚开始时,初始化程序块是做某些事情的唯一方法,但是现在它们变得混乱,容易出错,并且在大多数情况下,它们已被更好的替代方法替代(上面有详细说明)。知道初始化程序块是很有趣的,以防您在遗留代码中看到它们,或者它们正在测试中,但是如果我正在进行代码审查并且看到新代码中的一个,我会要求您说明为什么没有一个在您的代码通过之前,上述替代方法是合适的。