Java使用构造方法来对单个对象进行初始化操作,使用构造方法先完成整个Java对象的状态初始化,然后将Java对象返回给程序,从而让该Java对象的信息更加完整。与构造方法作用非常类似的是初始化块,它也可以对Java对象进行初始化操作。从某种程度上来看,初始化块是构造方法的补充,初始化块总是在构造方法执行之前执行。
一个类里可以有多个初始化块,相同类型的初始化块之间有顺序:前面定义的初始化块先执行,后面定义的初始化块执行。
初始化块的定义格式:
[修饰符] {
//初始化块的可执行性代码
}
初始化块的修饰符只能是static,使用static修饰的初始化块被称为静态初始化。初始化块里的代码可以包含任何可执行性语句,包括定义局部变量 ,调用其他对象的方法,以及使用分支,循环语句等。
初始化块跟构造方法不同的是初始化块是一段固定执行的代码,它不能接收任何参数。
通过把多个构造方法中的相同代码提取到初始化块中定义,能更好地提高初始化代码的复用,提高整个应用的可维护性。
静态初始化块:
如果定义初始化块时使用了static修饰符,则这个初始化块就变成了静态初始化块,也被称为类初始化块。静态初始化块是类相关的,系统将在类初始化阶段执行静态初始化块,而不是在创建对象时才执行。因此静态初始化块总是比普通初始化块先执行。静态初始化块也属于类的静态成员,同样需要遵循静态成员不能访问非静态成员的规则,因此静态初始化块不能访问非静态成员。
属性、方法、构造方法和自由块都是类中的成员,在创建类的对象时,类中各成员的执行顺序:
1.父类静态成员和静态初始化快,按在代码中出现的顺序依次执行。
2.子类静态成员和静态初始化块,按在代码中出现的顺序依次执行。
3. 父类的实例成员和实例初始化块,按在代码中出现的顺序依次执行。
4.执行父类的构造方法。
5.子类实例成员和实例初始化块,按在代码中出现的顺序依次执行。
6.执行子类的构造方法。
静态初始化块和非静态初始化块的区别?
非静态初始化块主要是用于对象的初始化操作,在每次创建对象的时都要调用一次,其执行顺序在构造方法之前。
在初始化块之前有static修饰,则为静态初始化块。由于非静态成员不能在静态方法中使用,同样也不能在静态初始化块中,因此,静态初始化块主要用于初始化静态变量和静态方法,静态初始化块只调用一次,是在类的第一次加载到内存时,并非一定要创建对象才执行。
静态初始化块比非静态初始化块先执行。
我们可以看一段代码示例,执行顺序可以很明显的看出:
class Root {
static {
System.out.println("Root的静态初始化块");
}
{
System.out.println("Root的普通初始化块");
}
public Root(){
System.out.println("Root 的无参数的构造器");
}
}
class Mid extends Root{
static {
System.out.println("Mid 的静态初始化块");
}
{
System.out.println("Mid 的普通初始块");
}
public Mid(){
System.out.println("Mid的无参数的构造器");
}
public Mid(String msg){
this();
System.out.println("Mid 的带参数构造器,其参数值: " + msg);
}
}
class Leaf extends Mid {
static{
System.out.println("Leaf的静态初始化块");
}
{
System.out.println("Leaf的普通初始化块");
}
public Leaf(){
super("test");
System.out.println("执行Leaf的构造器");
}
}
public class Test {
public static void main(String[] args){
new Leaf();
new Leaf();
}
}
运行结果:
Root的静态初始化块
Mid 的静态初始化块
Leaf的静态初始化块
Root的普通初始化块
Root 的无参数的构造器
Mid 的普通初始块
Mid的无参数的构造器
Mid 的带参数构造器,其参数值: test
Leaf的普通初始化块
执行Leaf的构造器
Root的普通初始化块
Root 的无参数的构造器
Mid 的普通初始块
Mid的无参数的构造器
Mid 的带参数构造器,其参数值: test
Leaf的普通初始化块
执行Leaf的构造器
从结果我们可以看出,静态初始化块最先执行,并且我们虽然创建了两个对象,但只执行了一次,充分印证了静态初始化块只调用一次的观点。各方法的执行顺序与我们上面所说的顺序一致。