这直接来自http://www.programcreek.com/2011/10/java-class-instance-initializers/
1. 执行顺序
看看下面这个类,你知道哪个是最先执行的吗?
public class Foo {
//instance variable initializer
String s = "abc";
//constructor
public Foo() {
System.out.println("constructor called");
}
//static initializer
static {
System.out.println("static initializer called");
}
//instance initializer
{
System.out.println("instance initializer called");
}
public static void main(String[] args) {
new Foo();
new Foo();
}
}
输出:
称为静态初始化程序
实例初始化程序调用
构造函数调用
实例初始化程序调用
构造函数调用
2. Java 实例初始化器是如何工作的?
上面的实例初始化程序包含一个 println 语句。要了解它是如何工作的,我们可以将其视为变量赋值语句,例如b = 0
. 这可以使它更容易理解。
代替
int b = 0
,你可以写
int b;
b = 0;
因此,实例初始化器和实例变量初始化器几乎相同。
3. 实例初始化器什么时候有用?
实例初始化器的使用很少见,但在以下情况下,它仍然可以作为实例变量初始化器的有用替代方案:
- 初始化代码必须处理异常
- 执行无法用实例变量初始化程序表达的计算。
当然,这样的代码可以写在构造函数中。但是如果一个类有多个构造函数,你将不得不在每个构造函数中重复代码。
使用实例初始化器,您只需编写一次代码,无论使用什么构造函数创建对象,它都会执行。(我猜这只是一个概念,并不经常使用。)
实例初始化器有用的另一种情况是匿名内部类,它根本不能声明任何构造函数。(这会是放置日志功能的好地方吗?)
感谢德海因。
另请注意,实现接口 [1] 的匿名类没有构造函数。因此,在构造时需要实例初始化器来执行任何类型的表达式。