java类成员初始化顺序

我们都知道要使用类,一般都需要先new出实例然后再使用。而类包含行为和状态,也有静态非静态之分。在使用实例的成员时候必须确保已经分配资源。
java中将基本类型赋值为初始值,如int类型的赋值为0,引用类型的赋值为null。

那静态成员、非静态成员、构造函数,这几个的执行顺序如何?

静态 -> 非静态成员 -> 构造函数

  1. 静态成员在类第一次被访问,实例化、触摸任一静态成员,的时候初始化且仅此一次
  2. 之所以要先初始化非静态字段,是因为构造函数允许开发者改变其值

那如果B类继承子A类, 实例化B,两个类中的静态/非静态、构造函数的执行顺序又是如何?

父类静态成员 -> 子类静态成员 -> 父类非静态成员 -> 父类构造函数 -> 子类非静态成员 -> 子类构造函数

继承主要是为了复用父类资源,然后扩展特性操作;那么在实例化子类的时候就先要获取到父类的实例,然后再实例化自身。这里要注意的是,子类的静态成员初始化紧跟在父类静态成员的初始化之后, 接着才是按照继承体系 非静态成员 -> 构造函数 这样子的顺序初始化; 当然, 在子类中也可以显式地调用super改变

以下是执行过程:

public class ClassLoadingOrder {
    public static void main(String[] args) {
        System.out.println("class loading start: ");
        System.out.println();
        Beetle beetle = new Beetle();
    }
}

/**
 * 父类 昆虫
 */
class Insect {
    // 私有字段
    private int i = 9;
    // 保护字段
    protected int j;
    // 私有静态字段
    private static int x1 = printInit("static Insect.x1 initialized");

    // 构造函数
    Insect() {
        print("Insect start initializing");
        print("i = " + i + ", j = " + j);
        j = 39;
    }

    // 帮助方法
    static int printInit(String s) {
        print(s);
        return 47;
    }
    static void print(String msg) {
        System.out.println(msg);
    }
}

/**
 * 子类 甲虫
 */
class Beetle extends Insect {

    // 私有字段
    private int k = printInit("Beetle.k initialized");
    // 私有静态字段
    private static int x2 = printInit("static Beetle.x2 initialized");

    // 构造函数
    Beetle() {
        print("Beetle start initializing");
        print("k = " + k);
        print("j = " + j);
    }
}

输出:

class loading start: 

static Insect.x1 initialized
static Beetle.x2 initialized
Insect start initializing
i = 9, j = 0
Beetle.k initialized
Beetle start initializing
k = 47
j = 39

你可能感兴趣的:(java类成员初始化顺序)