换句话说,你为什么需要一个实例初始化器?在编写实例初始化程序而不是构造函数时,您有什么区别或优势?
7 回答
这似乎很好地解释了它:
在以下情况下,实例初始化器是实例变量初始化器的有用替代方案:
初始化代码必须捕获异常,或者
执行无法用实例变量初始化器表达的奇特计算。当然,您可以始终在构造函数中编写此类代码。
但是在具有多个构造函数的类中,您必须在每个构造函数中重复代码。使用实例初始化器,您只需编写一次代码,无论使用什么构造函数创建对象,它都会执行。实例初始化器在匿名内部类中也很有用,它根本不能声明任何构造函数。
来自:JavaWorld Java 中的对象初始化。
在对象生命周期方面,没有区别。两者都在构造时调用,逻辑上初始化块可以被认为是构造的一部分。
从语义上讲,初始化器是一个很好的工具,有几个原因:
初始化程序可以通过将初始化逻辑保留在正在初始化的变量旁边来提高代码的可读性:
public class Universe {
public int theAnswer;
{
int SIX = 6;
int NINE = 7;
theAnswer = SIX * NINE;
}
// a bunch of other vars
}
对比
public class Universe {
public int theAnswer;
// a bunch of other vars
public Universe() {
int SIX = 6;
int NINE = 7;
theAnswer = SIX * NINE;
// other constructor logic
}
}
无论使用哪个构造函数,都会调用初始化程序。
初始化器可用于匿名内部类,而构造器则不能。
当您有许多构造函数并希望为每个构造函数执行一些通用代码时,您可以使用实例初始化程序。因为它被所有构造函数调用。
一般来说,我会避免使用实例初始化器惯用语——它相对于变量初始化器的唯一真正优势是异常处理。
而且由于 init 方法(可从构造函数调用)也可以进行异常处理并集中构造函数设置代码,但具有可以对构造函数参数值进行操作的优点,我会说实例初始化程序是多余的,因此要避免。
当我们使用匿名内部类时,实例初始化器相对于构造器的真正优势就体现出来了。
匿名内部类不能有构造函数(因为它们是匿名的), 因此它们非常适合实例初始化程序。
在创建对象时,如果我们要执行实例变量的初始化,那么我们应该使用构造函数,如果我们想在创建对象时执行任何活动,那么我们应该使用实例块。
我们不能用实例块替换构造函数,因为构造函数可以带参数,但实例块不能带参数。
我们不能用构造函数替换实例块,因为一个类可以包含多个构造函数。如果我们想用构造函数替换实例块,那么在每个构造函数中我们都必须编写实例块代码,因为在运行时我们无法预料会调用哪个构造函数,这会不必要地增加重复代码。
例子 :
class MyClass{
static int object_count = 0;
MyClass(){
object_count++;
}
MyClass(int i){
object_count++;
}
void getCount() {
System.out.println(object_count);
}
public static void main(String... args) {
MyClass one = new MyClass();
MyClass two = new MyClass(2);
two.getCount();
}
}
输出 : 2
class MyClass{
static int object_count = 0;
{
object_count++;
}
MyClass(){
}
MyClass(int i){
}
void getCount() {
System.out.println(object_count);
}
public static void main(String... args) {
MyClass one = new MyClass();
MyClass two = new MyClass(2);
two.getCount();
}
}
输出 : 2
初始化程序是在构造函数之间共享代码的方式,如果初始化程序与变量声明一起使用,它会使代码更具可读性。
Java 编译器将初始化程序块复制到每个构造函数中。因此,这种方法可用于在多个构造函数之间共享代码块。 甲骨文文档