代码的执行结果打印什么?
class B extends Object
{
static
{
System.out.println("Load B");
}
public B()
{
System.out.println("Create B");
}
}
class A extends B
{
static
{
System.out.println("Load A");
}
public A()
{
System.out.println("Create A");
}
}
public class Testclass
{
public static void main(String[] args)
{
new A();
}
}
一、类加载阶段(静态初始化)
父类优先加载的原因Java类的加载遵循「向上委托机制」。当加载器尝试加载子类时,发现它继承自父类,会先确保父类已被加载(如果父类未被加载过)。底层逻辑:子类的字节码中可能直接引用父类的字段或方法,必须确保父类先存在。
静态代码块的执行顺序父类静态代码块 → 子类静态代码块只执行一次(类首次被加载时),且父类优先于子类。
发现A继承B → 先检查B是否加载
加载B → 执行B的静态块(输出Load B)
加载A → 执行A的静态块(输出Load A)
二、对象实例化阶段
(1) 实例初始化顺序
父类普通代码块 → 父类构造方法 → 子类普通代码块 → 子类构造方法
为什么父类优先?子类构造方法默认隐含super()调用(除非显式调用其他父类构造方法)。super()会触发父类构造方法的执行。
父类构造方法执行前会先执行父类的普通代码块。因为代码块用于给属性进行初始化。
(2) 详细流程(以 new A() 为例)
// 1. 父类B的实例初始化
B的普通代码块 → B的构造方法(输出`Create B`)
// 2. 子类A的实例初始化
A的普通代码块 → A的构造方法(输出`Create A`)
注意:普通代码块在所属构造方法内的super()之后执行,但在本类构造方法剩余代码之前执行。
三、完整顺序总结(继承关系)
类加载阶段父类静态块 → 子类静态块(只执行一次,优先级最高)
对象实例化阶段父类普通代码块 → 父类构造方法子类普通代码块 → 子类构造方法 (每次new都会执行)
#四、其他的
- 为什么父类加载完子类才能加载?
技术本质:子类的类结构(如方法表)依赖父类信息。
JVM在解析子类时,需要确保父类的字段、方法等元数据已存在,否则无法正确构建子类的内存结构。 - 为什么父类普通代码块先于子类执行?
构造方法链规则:子类构造方法必须通过super()调用父类构造方法。
父类构造方法执行前,会先执行父类的普通代码块(可以理解为父类构造方法的一部分)。