一、前言
本题是关于代码块的执行问题,代码块分为两种,实例代码块和静态代码块,区别是有无static修饰,有关代码块的知识点下面我会根据本题细细讲解
二、代码
public class Test {
public static void main(String[] args) {
new B();
}
}
class A{
static {
System.out.println("Static-A执行了");//1
}
{
System.out.println("代码块-A执行了");//4
}
public A(){
System.out.println("构造器A执行了");//5
}
}
class B extends A {
static C c = new C();
static {
System.out.println("Static-B执行了");//3
}
{
System.out.println("代码块-B执行了");//6
}
public B(){
//super();
//代码块
System.out.println("构造器B执行了");//7
}
}
class C{
public C(){
System.out.println("构造器C执行了");//2
}
}
三、解析
3.1 前置知识
类的加载会触发类静态成员的执行,并且这种现象仅在类的第一次加载出现。然而每创建一次对象,实例代码块就会被执行一次,并且执行的时间早于构造器的执行,一般用来初始化实例变量或者做一些其它业务
3.2 详解
1、首先主方法创建了一个类B的对象,即将加载类B
2、进入到类B中,突然发现类B继承自类A,程序转头就去加载类A了(第一次加载类A)
3、加载类A,发现类A有一个静态成员,即静态代码块,执行里面的代码
4、加载完类A后返回并加载类B(第一次加载类B),发现类B有两个静态成员,从上往下的顺序依次执行,首先创建类C的对象,程序转头又就去加载类C(第一次执行类C)
5、类C里面没有静态成员和实例代码块,所以直接执行构造方法
6、回到类B,执行第二个静态成员,即静态代码块,然后即将执行类B的构造方法,但是发现构造器里面第一行隐藏调用了super(即调用父类的构造方法),父类构造器的优先级比实例代码块高,转头又跳到类A(此时不会再加载类A)
7、在类A中程序发现有实例代码块,就优先执行实例代码块,然后再执行构造器的代码
8、回到类B,即将执行类B的构造器,发现有实例代码块,先执行实例代码块,再执行构造器的代码
最后完结撒花~~~
四、拓展
4.1 类加载
什么时候会触发类加载呢?
1、调用静态成员的时候,会加载静态成员所处的类和父类,但是当子类继承父类,用子类对象名调用父类的静态成员变量并不会触发子类的加载,而是会加载父类。
2、当有继承关系时,加载子类先会触发父类的加载
3、第一次new对象的时候会触发类的加载,第二次则不会,并且一个类只会加载一次
4、当类中有pulic static final 定义的常量时,调用常量不会触发类的加载
4.2 代码块的执行顺序
静态成员 -> super() -> 实例代码块 -> 构造器
五、总结
通过本文我们学习了代码块的执行顺序,并拓展了类加载的知识,学到了什么时候会触发类的加载,还是那句话,如果虚心接受错误,如果对你有帮助记得一键三连!!!