Java中的初始化块、静态初始化快和构造器方法的执行顺序

 先放结论:

1.类的初始化阶段,先执行最顶层的父类的静态初始化块,然后依次向下执行,直到执行当前类的静态初始化块   

2.对象初始化阶段,先执行最顶层父类的初始化块,最顶层父类的构造器,然后依次向下,直到执行当前类的初始化块当前类的构造器。

3.当第二次创建对象时,由于这些类在第一次创建对象时已经被加载过了,因此静态初始化块只会执行一次。

总结一下三者的执行顺序:

1.父类的静态初始化块

2.子类的静态初始化块

3.父类的初始化块

4.父类的构造函数

5.子类的初始化块

6.子类的构造函数

当有this()调用的时候会先进入到构造器中,但并不执行,大约如下图所示: 

最近在看java核心技术,今天刚看到对象构造的时候,作者说对象初始化块的执行是先于构造器的,但是下面这段代码的结果令我感到有些困惑:

import java.util.*;

/**
 * This program demonstrates object construction.
 * @version 1.01 2004-02-19
 * @author Cay Horstmann
 */
public class ConstructorTest
{
   public static void main(String[] args)
   {
      // fill the staff array with three Employee objects
      Employee[] staff = new Employee[3];

      staff[0] = new Employee("Harry", 40000);
      staff[1] = new Employee(60000);
      staff[2] = new Employee();

      // print out information about all Employee objects
      for (Employee e : staff)
         System.out.println("name=" + e.getName() + ",id=" + e.getId() + ",salary="
               + e.getSalary());
   }
}

class Employee
{
   private static int nextId;

   private int id;
   private String name = ""; // instance field initialization
   private double salary;
  
   // static initialization block
   static
   {
      Random generator = new Random();
      // set nextId to a random number between 0 and 9999
      nextId = generator.nextInt(10000);
   }

   // object initialization block
   {
      id = nextId;
      nextId++;
   }

   // three overloaded constructors
   public Employee(String n, double s)
   {
      name = n;
      salary = s;
   }

   public Employee(double s)
   {
      // calls the Employee(String, double) constructor
      this("Employee #" + nextId, s);
   }

   // the default constructor
   public Employee()
   {
      // name initialized to ""--see above
      // salary not explicitly set--initialized to 0
      // id initialized in initialization block
   }

   public String getName()
   {
      return name;
   }

   public double getSalary()
   {
      return salary;
   }

   public int getId()
   {
      return id;
   }
}

执行的结果为是这样子的:

name=Harry,id=7943,salary=40000.0
name=Employee #7944,id=7944,salary=60000.0
name=,id=7945,salary=0.0

我认为的是staff[1]在实例化的时候会先执行初始化块,然后执行含参构造方法 Employee(double s),这会导致这个对象的id和name不一致,例如id=7944而name=7945,但结果是正确的,原因正如上图所示。

在Java中,有两种初始化块:静态初始化块和非静态初始化块。它们都是定义在类中,用大括号{}括起来,静态代码块在大括号外还要加上static关键字。

非静态初始化块(构造代码块):
作用:给对象进行初始化。对象一建立就运行,且优先于构造函数的运行。
与构造函数的区别:非静态初始化块给所有对象进行统一初始化,构造函数只给对应对象初始化。
应用:将所有构造函数共性的东西定义在构造代码块中。

静态初始化块:
作用:给类进行初始化。随着类的加载而执行,且只执行一次
与构造代码块的区别:
1)构造代码块用于初始化对象,每创建一个对象就会被执行一次;静态代码块用于初始化类,随着类的加载而执行,不管创建几个对象,都只执行一次。
2)静态代码块优先于构造代码块的执行
3)都定义在类中,一个带static关键字,一个不带static

构造器、非静态初始化块、静态代码块都是用于初始化,三者的执行顺序依次是:静态代码块>构造代码块>构造器。
其实初始化块就是构造器的补充,初始化块是不能接收任何参数的,定义的一些所有对象共有的属性、方法等内容时就可以用初始化块初始化了。

静态初始化块的作用就是当JVM在装载类时,你想让它做一些事情,那么,就可以用静态初始化块。这几者的执行顺序是:

(JVM在装载类时)先装载类的静态成员,再执行静态初始化块(同样,当一个类有继承自某类时,则会先装载该父类,那么,父类的装载或执行顺序,也都如句子所述)。

(在创建类的实例时)先执行实例初始化块,再执行构造方法;但对于一棵继承树中,会先调用父类的构造方法,那么其执行顺序也如句子所述。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值