我们都知道要使用类,一般都需要先new出实例然后再使用。而类包含行为和状态,也有静态非静态之分。在使用实例的成员时候必须确保已经分配资源。
java中将基本类型赋值为初始值,如int类型的赋值为0,引用类型的赋值为null。
那静态成员、非静态成员、构造函数,这几个的执行顺序如何?
静态 -> 非静态成员 -> 构造函数
- 静态成员在类第一次被访问,实例化、触摸任一静态成员,的时候初始化且仅此一次
- 之所以要先初始化非静态字段,是因为构造函数允许开发者改变其值
那如果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
网友评论