一.无继承关系的情况下
在Java中,类的初始化顺序涉及到多个方面,包括静态变量、静态初始化块、实例变量、实例初始化块(也称为构造器初始化块或初始化块)以及构造器的执行顺序。这里是一个详细的顺序说明:
- 静态变量和静态初始化块:
- 当类被加载到JVM时,类的静态成员(静态变量和静态初始化块)会被初始化。
- 静态初始化块和静态变量的初始化顺序取决于它们在类定义中出现的顺序。
- 静态初始化块只会在类被加载时执行一次,不管创建了多少个类的实例。
- 实例变量和实例初始化块:
- 当创建类的实例时,实例变量和实例初始化块会被初始化。
- 实例初始化块(如果没有使用显式构造函数或者使用了无参构造函数)在每次创建类的实例时都会执行。
- 实例初始化块和实例变量的初始化顺序也取决于它们在类定义中出现的顺序。
- 构造器:
- 在所有静态成员初始化之后,当创建类的实例时,相应的构造器会被调用。
- 构造器负责初始化实例变量(如果它们还没有在实例初始化块或声明时初始化),并执行任何必要的初始化代码。
- 如果类定义了多个构造器,则根据创建实例时使用的构造器来执行相应的初始化代码。
- 总结顺序:
- 静态变量和静态初始化块(按照它们在类中出现的顺序)
- 实例变量和实例初始化块(按照它们在类中出现的顺序,每次创建实例时)
- 构造器(每次创建实例时)
注意:
- 静态初始化块和静态变量只会在类加载时初始化一次。
- 实例初始化块和实例变量会在每次创建类的实例时初始化。
二.有继承关系的情况下
在Java中,当存在继承关系时,类的初始化顺序会遵循一定的规则。这些规则确保了父类在子类之前被正确地初始化和构造,从而保证了继承关系的正确性和对象的完整性。以下是具体的初始化顺序:
- 静态变量和静态初始化块:
- 首先,会初始化父类的静态变量和静态初始化块(如果有的话),按照它们在父类中出现的顺序进行。
- 然后,会初始化子类的静态变量和静态初始化块(如果有的话),同样按照它们在子类中出现的顺序进行。
- 需要注意的是,静态成员(静态变量和静态初始化块)的初始化只会在类被加载到JVM时发生一次,与创建多少个类的实例无关。
- 实例变量和实例初始化块:
- 当创建子类的实例时,会先初始化父类的实例变量和实例初始化块(如果有的话),按照它们在父类中出现的顺序进行。
- 接着,会初始化子类的实例变量和实例初始化块(如果有的话),同样按照它们在子类中出现的顺序进行。
- 构造器:
- 在所有静态成员和实例成员初始化之后,会调用子类的构造器。
- 在子类构造器执行之前,会先隐式或显式地调用父类的构造器(如果子类构造器中没有显式调用父类的其他构造器,则默认调用父类的无参构造器)。
- 父类构造器负责初始化父类的实例变量(如果它们还没有在父类的实例初始化块或声明时初始化),并执行父类的构造器代码。
- 接着,子类构造器会执行,负责初始化子类的实例变量(如果它们还没有在子类的实例初始化块或声明时初始化),并执行子类的构造器代码。
综上所述,Java中继承关系的类的初始化顺序为:
- 父类静态变量和静态初始化块(按出现顺序)。
- 子类静态变量和静态初始化块(按出现顺序)。
- 父类实例变量和实例初始化块(按出现顺序)。
- 父类构造器。
- 子类实例变量和实例初始化块(按出现顺序)。
- 子类构造器。