详解Java中的实例初始化块(IIB)
在Java语言中的类初始化块文章中我们简单的介绍了下Java中的实例初始化块(IIB)。不过我觉得介绍的有点简单了,于是,再写一篇文章详细介绍下吧。
Java语言中,存在三种操作:方法、构造函数和初始化块。
其中初始化块又分为实例初始化块(IIB)和静态初始化块。本章节,我们主要介绍实例初始化块。
实例初始化块用于初始化实例变量。
实例初始化块会在初始化类的一个实例时执行,而且在构造函数之前就执行。并且每次创建类的对象时它们都会执行。
实例化块的语法
实例初始化块一般放在构造函数之前,使用大括号{}扩起来的代码。语法结构一般如下
classJavaTester { //实例化块 { System.out.println("IIBblock"); } //构造函数 JavaTester() { System.out.println("ConstructorCalled"); } publicstaticvoidmain(String[]args) { JavaTestera=newJavaTester(); } }
注意,实例化块并不是类的必须。只是一个可选项。用于抽出构造函数的公共部分单独执行而已。
这段代码是可以编译运行的,运行结果如下
[yufei@www.twle.cnjava]$javacJavaTester.java&&javaJavaTester IIBblock ConstructorCalled
一个类中包含多个实例初始化块
类中的实例初始化块并不是类所必须的,而且,不限数量。一个类既可以没有实例初始化块,也可以有多个实例初始化块。
如果一个类有多个实例初始化块,那么它们会按照顺序从上到下依次执行,也就是说,定义在类顶部的实例初始化块最先执行。
我们来看一段代码,下面的类JavaTester定义了多个实例初始化块。
classJavaTester { { System.out.println("IIB1block1"); } { System.out.println("IIB2block2"); } JavaTester() { System.out.println("ConstructorCalled"); } { System.out.println("IIB3block3"); } publicstaticvoidmain(String[]args) { JavaTestera=newJavaTester(); } }
运行上面这段代码,输出结果如下
[yufei@www.twle.cnjava]$javacJavaTester.java&&javaJavaTester IIB1block1 IIB2block2 IIB3block3 ConstructorCalled
父类中的初始化块
在Java语言的继承体系中,父类同样可以有初始化块,而且数量不限。
父类的实例初始化块在子类的构造函数中调用super()之后立即运行。编译器会在执行当前类的实例初始化块之前先执行父类的实例初始化块。
是不是很绕口,我们写一段代码来演示下
classB { B() { System.out.println("B-ConstructorCalled"); } { System.out.println("B-IIBblock"); } } publicclassJavaTesterextendsB { { System.out.println("JavaTesterIIB1block1"); } { System.out.println("JavaTesterIIB2block2"); } JavaTester() { super(); System.out.println("JavaTester-ConstructorCalled"); } { System.out.println("JavaTesterIIB3block3"); } publicstaticvoidmain(String[]args) { JavaTestera=newJavaTester(); } }
运行以上范例,输出结果如下
[yufei@www.twle.cnjava]$javacJavaTester.java&&javaJavaTester B-IIBblock B-ConstructorCalled JavaTesterIIB1block1 JavaTesterIIB2block2 JavaTesterIIB3block3 JavaTester-ConstructorCalled
从运行的结果来看,当创建类JavaTester的对象时,编译器尝试执行类JavaTester的构造函数。但因为它有一个父类,在发现了super()语句后,就转而先执行父类的构造函数。
因此,在继承体系中,实例初始化块和构造函数的执行顺序如下
执行父类的实例初始化块
执行父类的构造函数
执行当前类的实例初始化块
执行当前类的构造函数
实例初始化块的要点
我们一起来回顾下实例初始化块的要点。
每次创建新实例时都会运行实例初始化块
初始化块按它们在类中出现的顺序运行
如果存在父类,则首先会实例化父类然后在调用当前类的实例初始化块,最后再调用当前类的构造函数。