核心逻辑(适用于大多数OOP语言)
执行顺序铁律:
父类静态 → 子类静态 → 父类实例 → 子类实例
(静态数据只初始化一次,实例数据每次new
都执行)
📊 通用执行顺序流程图
css
mermaid
graph TD
A[父类静态成员初始化] --> B[子类静态成员初始化]
B --> C[父类实例成员初始化]
C --> D[父类构造函数]
D --> E[子类实例成员初始化]
E --> F[子类构造函数]
🛠️ 关键概念解析
1. 静态 vs 非静态
特性 | 静态成员 | 非静态成员 |
---|---|---|
初始化时机 | 类加载时(仅一次) | 每次实例化时 |
内存分配 | 全局唯一 | 每个实例独立一份 |
访问方式 | 类名.成员 |
实例.成员 |
2. 类加载阶段(语言无关)
- 加载 :读取类定义(如
.class
/.dll
文件) - 验证:检查语法/安全性
- 准备:为静态变量分配内存(赋默认值)
- 解析:处理符号引用
- 初始化:执行静态代码和静态变量赋值
3. 实例化阶段
- 分配实例内存
- 初始化实例变量
- 执行构造函数
🌰 伪代码示例
场景:父类与子类初始化
scala
plaintext
class Parent:
static:
print("父类静态初始化")
instance:
print("父类实例初始化")
constructor():
print("父类构造函数")
class Child extends Parent:
static:
print("子类静态初始化")
instance:
print("子类实例初始化")
constructor():
print("子类构造函数")
// 测试
obj = new Child()
输出结果:
markdown
父类静态初始化
子类静态初始化
父类实例初始化
父类构造函数
子类实例初始化
子类构造函数
-
默认值优先
所有静态变量会先赋默认值(如
int=0
),再执行显式赋值:inijava static int a = 5; static { a = 10; } // 最终a=10(默认0 → 赋5 → 赋10)
**✅ 终极总结**
-
类加载时:静态成员(变量/代码块)按父→子顺序初始化
-
实例化时:
- 父类实例成员 → 父类构造
- 子类实例成员 → 子类构造
-
静态只一次:无论创建多少实例,静态数据仅初始化一次
需要注意 类加载的时候会上锁 其他线程会阻塞