大致可分为分为两种情况,在本类的关系中和在子类与父类的关系中的执行顺序。
- 在本类中
首先贴出如下代码:
package testStatic;
/*
* 测试 执行顺序
* 测试结果:静态初始化块>构造块>构造方法
*/
public class TestStatic {
TestStatic(){
System.out.println("构造方法");
}
{
System.out.println("构造块");
}
static {
System.out.println("静态初始化块");
}
public static void main(String[] args) {
TestStatic c = new TestStatic();
}
}
从代码的执行结果上看,最终的执行顺序为:静态初始化块>构造块>构造方法。其中构造快和构造方法都是在通过创建实体对象时同时创建和分配空间的。
- 在子类继承同样有静态初始化块,构造块,构造方法的父类,并创建子类对象;
package testStatic;
/*
* 测试在子类中相关的调用顺序
* 测试结果:父类的静态初始化块,子类的静态初始化块,父类的构造块,父类的构造方法,子类的构造块,子类的构造方法
*/
public class StaticExtends extends Father{
StaticExtends(){
System.out.println("子类构造方法");
}
static {
System.out.println("子类静态初始化块");
}
{
System.out.println("子类构造块");
}
public static void main(String[] args) {
StaticExtends sta = new StaticExtends();
}
}
class Father{
Father(){
System.out.println("父类构造方法");
}
static {
System.out.println("父类静态初始化块");
}
{
System.out.println("父类构造块");
}
}
从测试结果中可以看出,子类中创建子类对象是,首先从上追溯,调用了父类中无参的构造器,此时即调用了父类中的静态初始化块(类中的静态属性和静态方法,以及静态块归属于类;故类声明后即会为静态属性分配空间),然后由于静态初始化块的优先级总是大于构造块与构造方法;故再调用子类的静态初始化块。然后是父类的构造块和构造方法的优先级高于子类的,所以最终先调用父类的构造块和构造方法,再调用子类的构造块和构造方法。
在一个类中可能有多个静态初始化块和多个静态属性,此时应遵循自顶向下的原则:即按照由上而下的执行顺序。如:
package testStatic;
public class StaticOrder {
public static StaticOrder ode = new StaticOrder();
{
System.out.println("构造快");
}
static {
System.out.println("静态初始化块");
}
public static void main(String[] args) {
}
}
运行后的输出结果为:构造块,静态初始化块;