原则:
1、父类优先于子类进行初始化;
2、变量优先于方法进行初始化;
3、静态优(对象或变量)先于非静态,而静态只初始化一次;
实验:方法和变量的执行顺序
结论:
不论变量放在哪儿,都会先于任意一个方法的执行前执行(包括构造方法),而构造方法是一个类必须会执行的方法,不需要显示的进行调用。同时,不论变量在哪儿分布,只要在方法外部,就一定先于方法初始化。
public class Main {
public Main(int n) {
System.out.println("Main类构造函数执行!" + "第" + n + "个");
}
public static void main(String[] args) {
Test t = new Test();
}
}
class Test {
Main m1 = new Main(1); //类变量总是比方法先执行
public Test() {
System.out.println("Test类构造函数执行!");
Main m2 = new Main(2); //方法中构造方法先执行;
}
Main m3 = new Main(3); //不管类变量在哪里,都是类变量比方法先执行;
}
/*输出:
Main类构造函数执行!第1个
Main类构造函数执行!第3个
Test类构造函数执行!
Main类构造函数执行!第2个
*/
实验:static块和非static块
结论:
静态块是在类的装载时执行的(装入.class文件后), 且只执行一次。而非静态块是在调用构造方法之前执行的,每生成一个实例对象,就会调用一次非静态块。
public class Main {
//静态块(static块)
static {
System.out.println("静态块!");
}
//非静态块
{
System.out.println("非静态块!");
}
public Main(int n) {
System.out.println("构造函数!" + "第" + n + "次");
}
public static void main(String args[]) {
Main m1 = new Main(1);
Main m2 = new Main(2);
}
}
/*输出:
* 静态块!
非静态块!
构造函数!第1次
非静态块!
构造函数!第2次
*/
Java类中的数据体执行顺序
1、先装载.class文件,创建Class对象,对静态数据(由static声明的)进行初始化,而且只进行一次初始化。
2、关键词”new”出对象,在堆上进行空间分配。
3、执行非静态块。
4、执行所有方法外定义的变量的初始化。
5、执行构造器。
即:静态块,静态属性->非静态块,属性->构造器
注:对于静态块和静态属性或者非静态块和属性,初始化顺序决定于它们在代码中的顺序(在前就先执行)。
public class Main {
static {
System.out.println("静态块!"); //加载class文件时执行,仅执行一次;
}
{
System.out.println("非静态块!"); //每次new时执行;
}
Test t1 = new Test(1);
public Main() {
System.out.println("Main类构造函数!");
Test t2 = new Test(2);
}
Test t3 = new Test(3);
public static void main(String args[]) {
Main m = new Main();
}
}
class Test {
public Test(int n) {
System.out.println("构造函数!" + "第" + n + "次");
}
}
/*输出:
静态块!
非静态块!
构造函数!第1次
构造函数!第3次
Main类构造函数!
构造函数!第2次
*/
总结:加载顺序
1) 父类(静态变量、静态语句块)
2) 子类(静态变量、静态语句块)
3) 父类(实例变量、普通语句块)
4) 父类(构造函数)
5) 子类(实例变量、普通语句块)
6) 子类(构造函数)
class BaseMain {
//父类代码块
static {
System.out.println("父类的static代码块,已执行!");
}
//父类非静态代码块
{
System.out.println("父类非静态代码块,已执行!");
}
//构造器
public BaseMain() {
System.out.println("父类构建器,已执行!");
}
}
public class Main extends BaseMain {
// 子类static代码块
static {
System.out.println("子类static代码块,已执行!");
}
// 子类非static代码块
{
System.out.println("子类非static代码块,已执行!");
}
// 子类构造器
public Main() {
System.out.println("子类构造器,已执行!");
}
// 程序入口
public static void main(String args[]) {
new Main();
}
}
/* 输出:
父类的static代码块,已执行!
子类static代码块,已执行!
父类非静态代码块,已执行!
父类构建器,已执行!
子类非static代码块,已执行!
子类构造器,已执行!
*/