天天看点

初始化块和构造器的执行顺序问题

一 初始化块和构造器的执行顺序问题一般性规定

1 初始化块总在构造器之前执行,初始化块不能接受形参。

2 用static修饰的初始化块为静态初始化块,由于是静态的,所以是属于类,当类加载时,就执行静态初始化块,但执行一个子类时,最先执行其顶层父类的静态初始化。

3 如果初始化块是属于实例的,只要创建一次对象,初始化块就执行一次。

二 初始化块和构造器综合应用

1 代码示例

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调用同一类中重载的构造器
    this();
    System.out.println("Mid的带参数构造器,其参数值:"
      + msg);
  }
}
class Leaf extends Mid
{
  static{
    System.out.println("Leaf的静态初始化块");
  }
  {
    System.out.println("Leaf的普通初始化块");
  }
  public Leaf()
  {
    // 通过super调用父类中有一个字符串参数的构造器
    super("软件秘笈");
    System.out.println("执行Leaf的构造器");
  }
}
public class Test
{
  public static void main(String[] args)
  {
    new Leaf();
    new Leaf();
  }
}      

 2 运行结果

Root的静态初始化块

Mid的静态初始化块

Leaf的静态初始化块

Root的普通初始化块

Root的无参数的构造器

Mid的普通初始化块

Mid的无参数的构造器

Mid的带参数构造器,其参数值:软件秘笈

Leaf的普通初始化块

执行Leaf的构造器

3 结果分析

3.1 第一次创建第一个Leaf对象时,因为系统中还不存在Leaf类,因此需要先加载并初始化Leaf类,初始化Leaf类时会先执行其顶层父类静态初始化,再执行其直接父类的静态初始化块,最后才执行Leaf本身静态初始化块。

3.2 一旦Leaf类初始化成功后,Leaf类在该虛拟机中将一直存在,因此,当第二次创建Leaf实例时无须再对Leaf类进行初始化。

3.3普通初始化块和构造顺序与前面介绍的一致,每次创建一个Leaf对象时,都需先执行最顶层父类的初始化,构造器,然后执行其父类初始化,构造器…最后才执行Leaf类的初始化块和构造器。

三 静态初始化块与指定初始化值的静态成员执行顺序问题

public class StaticInitTest
{
  // 先执行静态初始化块将a静态成员变量赋值为6
  static
  {
    a = 6;
  }
  // 再将a静态成员变量赋值为9
  static int a = 9;
  public static void main(String[] args)
  {
    // 下面代码将输出9
    System.out.println(StaticInitTest.a);
  }
}      

2 运行结果

9