您在选择时必须考虑一个重要方面:
初始化块是类/对象的成员,而构造函数不是。这在考虑扩展/子类化时很重要:
- 初始化器由子类继承。(虽然,可以被遮蔽)
这意味着基本上可以保证子类按照父类的意图进行初始化。
- 但是,构造函数不是继承的。(它们仅隐式调用[即无参数],或者您必须手动
super()
进行特定调用。)
这意味着隐式或显式调用可能不会按照父类的预期初始化子类。super(...)
super(...)
考虑这个初始化块的例子:
class ParentWithInitializer {
protected String aFieldToInitialize;
{
aFieldToInitialize = "init";
System.out.println("initializing in initializer block of: "
+ this.getClass().getSimpleName());
}
}
class ChildOfParentWithInitializer extends ParentWithInitializer{
public static void main(String... args){
System.out.println(new ChildOfParentWithInitializer().aFieldToInitialize);
}
}
输出:
initializing in initializer block of: ChildOfParentWithInitializer
init
-> 无论子类实现什么构造函数,该字段都会被初始化。
现在考虑这个带有构造函数的例子:
class ParentWithConstructor {
protected String aFieldToInitialize;
// different constructors initialize the value differently:
ParentWithConstructor(){
//init a null object
aFieldToInitialize = null;
System.out.println("Constructor of "
+ this.getClass().getSimpleName() + " inits to null");
}
ParentWithConstructor(String... params) {
//init all fields to intended values
aFieldToInitialize = "intended init Value";
System.out.println("initializing in parameterized constructor of:"
+ this.getClass().getSimpleName());
}
}
class ChildOfParentWithConstructor extends ParentWithConstructor{
public static void main (String... args){
System.out.println(new ChildOfParentWithConstructor().aFieldToInitialize);
}
}
输出:
Constructor of ChildOfParentWithConstructor inits to null
null
-> 这将null
默认初始化字段,即使它可能不是您想要的结果。