很多同学在学习Java 类加载机制时都会被这三个变量绕晕普通成员变量int a 10静态变量static int b 10静态常量static final int c 10明明都是赋值 10为什么 JVM 要分不同阶段处理今天我们就从类加载到对象创建把它们的生命周期、内存位置、赋值时机一次性讲清楚。一、先明确三个变量的 “身份”1. 普通成员变量int a 10属于对象关键字无 static生命周期和对象绑定对象创建才存在对象销毁就消失内存位置堆对象内部2. 静态变量static int b 10属于类关键字static生命周期和类绑定类加载后就存在内存位置方法区JDK8 后在元空间归类所有3. 编译期常量static final int c 10属于类关键字static final生命周期和类一致特点编译时就能确定值运行期不可修改二、类加载阶段只有静态相关变量会被处理Java 类加载流程加载 → 链接验证→准备→解析→ 初始化 → 使用 → 卸载我们重点看对这三个变量真正有影响的阶段1. 链接・准备阶段只干 “默认赋值”这个阶段 JVM 只做一件事为静态变量分配内存并赋系统默认值。int默认0boolean默认false引用类型默认null对三个变量的处理普通成员变量int a 10→完全不理因为它属于对象此时还没有对象连内存都不分。静态变量static int b 10→ 分配内存→ 赋值b 0系统默认值→ 你写的10这一步完全不执行。静态常量static final int c 10→ 这是特例→ 编译期已经确定值 10→ 准备阶段直接赋值 10不走默认值。2. 初始化阶段执行你写的代码初始化阶段会执行类构造器clinit()作用是按代码顺序给静态变量真正赋值、执行静态代码块。对三个变量的处理普通成员变量int a 10→还是不理和类加载无关。静态变量static int b 10→ 执行你写的代码b 10→ 这才是真正的 “业务赋值”。静态常量static final int c 10→ 已经在准备阶段赋完 10 了→ 这里不再处理。三、对象创建阶段只处理成员变量当你执行new 类名();才轮到成员变量出场。对象创建时赋值流程在堆中开辟对象内存给成员变量赋系统默认值a 0执行你写的赋值a 10对三个变量的处理普通成员变量int a 10→ 先 0 → 再 10→ 这是它第一次真正拥有值。静态变量static int b 10→ 类加载已经完成赋值→ 对象创建完全不影响它。静态常量static final int c 10→ 同理类加载就固定了→ 和对象无关。四、一张表看懂三者核心区别面试直接背变量类型归属准备阶段类加载初始化阶段类加载对象创建时内存位置普通成员变量int a10对象不理无内存不理先赋 0再赋 10堆对象内静态变量static int b10类分配内存赋 0赋真正值 10不理方法区static final 常量static final int c10类直接赋 10不理不理方法区五、最关键的 3 句总结一定要记住普通成员变量属于对象不 new 就不存在类加载全程不管只在创建对象时赋值。静态变量属于类类加载时先给默认值初始化阶段才给你代码里的真实值。static final 常量编译期就确定值准备阶段直接赋值一步到位。六、一句话收尾只要记住一句话静态的归类成员的归对象默认归准备真正赋值归初始化常量一步到位。
普通成员变量、静态变量、static final 常量的赋值全过程
很多同学在学习Java 类加载机制时都会被这三个变量绕晕普通成员变量int a 10静态变量static int b 10静态常量static final int c 10明明都是赋值 10为什么 JVM 要分不同阶段处理今天我们就从类加载到对象创建把它们的生命周期、内存位置、赋值时机一次性讲清楚。一、先明确三个变量的 “身份”1. 普通成员变量int a 10属于对象关键字无 static生命周期和对象绑定对象创建才存在对象销毁就消失内存位置堆对象内部2. 静态变量static int b 10属于类关键字static生命周期和类绑定类加载后就存在内存位置方法区JDK8 后在元空间归类所有3. 编译期常量static final int c 10属于类关键字static final生命周期和类一致特点编译时就能确定值运行期不可修改二、类加载阶段只有静态相关变量会被处理Java 类加载流程加载 → 链接验证→准备→解析→ 初始化 → 使用 → 卸载我们重点看对这三个变量真正有影响的阶段1. 链接・准备阶段只干 “默认赋值”这个阶段 JVM 只做一件事为静态变量分配内存并赋系统默认值。int默认0boolean默认false引用类型默认null对三个变量的处理普通成员变量int a 10→完全不理因为它属于对象此时还没有对象连内存都不分。静态变量static int b 10→ 分配内存→ 赋值b 0系统默认值→ 你写的10这一步完全不执行。静态常量static final int c 10→ 这是特例→ 编译期已经确定值 10→ 准备阶段直接赋值 10不走默认值。2. 初始化阶段执行你写的代码初始化阶段会执行类构造器clinit()作用是按代码顺序给静态变量真正赋值、执行静态代码块。对三个变量的处理普通成员变量int a 10→还是不理和类加载无关。静态变量static int b 10→ 执行你写的代码b 10→ 这才是真正的 “业务赋值”。静态常量static final int c 10→ 已经在准备阶段赋完 10 了→ 这里不再处理。三、对象创建阶段只处理成员变量当你执行new 类名();才轮到成员变量出场。对象创建时赋值流程在堆中开辟对象内存给成员变量赋系统默认值a 0执行你写的赋值a 10对三个变量的处理普通成员变量int a 10→ 先 0 → 再 10→ 这是它第一次真正拥有值。静态变量static int b 10→ 类加载已经完成赋值→ 对象创建完全不影响它。静态常量static final int c 10→ 同理类加载就固定了→ 和对象无关。四、一张表看懂三者核心区别面试直接背变量类型归属准备阶段类加载初始化阶段类加载对象创建时内存位置普通成员变量int a10对象不理无内存不理先赋 0再赋 10堆对象内静态变量static int b10类分配内存赋 0赋真正值 10不理方法区static final 常量static final int c10类直接赋 10不理不理方法区五、最关键的 3 句总结一定要记住普通成员变量属于对象不 new 就不存在类加载全程不管只在创建对象时赋值。静态变量属于类类加载时先给默认值初始化阶段才给你代码里的真实值。static final 常量编译期就确定值准备阶段直接赋值一步到位。六、一句话收尾只要记住一句话静态的归类成员的归对象默认归准备真正赋值归初始化常量一步到位。