Java代码执行顺序
- static修饰的方法或者代码块只在类加载时执行,类是用类加载器来读取的,类加载器是带有一个缓存区的,它会把读取到的类缓存起来,所以在一次虚拟机运行期间,一个类只会被加载一次。因此,静态代码块优先于其他代码执行且只会运行一次,静态方法优先于其他代码执行,但是静态代码块、静态方法等是根据上下顺序执行。(即静态代码块再上则优先执行静态代码块、静态方法在上则优先执行静态方法)
- 静态代码后是主方法开始执行,与静态代码块执行一次不同,若是主方法中不管通过什么再次调用了静态方法,静态方法仍可执行
- 若程序中存在普通代码块和构造方法,则调用构造方法之前会先执行普通代码块再执行构造方法,最后执行构造方法中的普通方法或者主程序后的普通方法
- 若是存在父子类关系,则父类中的静态代码优先于子类中的静态代码(父类加载优先于子类加载),若存在子类构造方法调用父类的构造方法,则先执行父类的构造方法再执行子类的构造方法。
总结:静态代码 -> main方法 -> 普通代码块 -> 构造方法 -> 普通方法
1.据下面的代码,可以来看看Java代码的执行顺序
public class Test06 {
public static Test06 si = new Test06();
public Test06() {
System.out.println("constructor");
m1();
System.out.println(si);
}
public static void m1() {
System.out.println("static method");
}
{ System.out.println("instance block"); }
static { System.out.println("static"); }
public static void main(String[] args) {
System.out.println("main start");
new Test06();
System.out.println("main end");
}
}
根据之前所述的Java代码运行顺序得到,在主方法调用之前先会进行类加载,静态的代码块或是方法会按照顺序执行,因此顺序为:
- 加载了一个静态的Test06类,并且调用了构造方法(new Test06),所以先加载普通代码块,输出"instance block"
- 进入到构造方法中,输出"constructor"
- 按顺序执行m1()方法,输出"static method"
- 输出si的地址值,此时并没有实例化一个对象,因此si的地址值为null
- 接着是静态代码块"instance block",但注意因为是类加载静态的变量、方法、代码块只加载一次,而之间已经加载过了静态m1()方法,因此这里会跳过静态的m1()方法去加载静态的代码块
- 类加载完毕后,主方法开始执行,因此先输出"main start"
- 然后是实例化了一个对象new Test06(); 这时会去调用Test06()构造方法,因此又执行一次普通代码块(优先于构造方法执行)输出"instance block"
- 然后进入构造方法中按顺序执行,输出"constructor"
- 调用m1()方法,输出"static method"
- 输出si的地址值
- 最后输出"main end",程序停止运行
//这是上述代码的运行结果
instance block
constructor
static method
null
static
main start
instance block
constructor
static method
com.zzxx.test.Test06@4554617c
main end
2.让我们再来看看这个
class Test1 {
public Test1() {
System.out.println("Test1");
}
{
System.out.println("I'm Test1 class");
}
static {
System.out.println("static Test1");
}
}
public class Test2 extends Test1 {
public Test2() {
System.out.println("Test2");
}
{
System.out.println("I'm Test2 class");
}
static {
System.out.println("static Test2");
}
public static void main(String[] args) {
new Test2();
}
}
根据之前所述的Java运行代码,来看看顺序
- 先进行类加载,由于父类优先于子类加载,因此先输出"static Test1"
- 接着加载子类输出static Test2
- 之后执行主方法,new Test2();调用Test2()构造方法,注意,此时是子类的无参构造方法,会默认有一个super()方法,因此在子类中其实的代码是这样的
public Test2() {
super();
System.out.println("Test2");
}
由此,先回去调用父类的构造方法,在这之前先执行父类中的普通代码块,输出"I’m Test1 class"
4. 调用Test1()输出"Test1"
5. 返回到子类中,优先于子类的构造方法先执行子类的普通代码块,输出"I’m Test2 class"
6. 然后执行Test2(),输出"Test2"
//用Java程序执行上述代码结果为
static Test1
static Test2
I'm Test1 class
Test1
I'm Test2 class
Test2