静态变量属于类、所有实例共享,存储于方法区(JDK 8+为元空间),随类加载初始化且仅一次;实例变量属于对象、各实例独立,存储于堆内存,每次new时初始化;静态变量可通过类名访问,实例变量须通过对象引用访问。

静态变量属于类,所有实例共享同一份;实例变量属于对象,每个实例独立一份。关键区别在生命周期、内存位置和访问方式。
内存位置不同
静态变量存储在方法区(JDK 8+ 是元空间),随类加载而分配,随类卸载而释放;实例变量存储在堆内存中,随对象创建而分配,随对象被垃圾回收而释放。
- 方法区是线程共享的,所以静态变量天然线程共享
- 堆也是线程共享的,但每个对象的实例变量彼此隔离,需通过对象引用访问
- 局部变量(如方法内定义的)在栈中,不在此讨论范围
初始化时机与生命周期不同
静态变量在类首次主动使用(如 new 实例、调用静态方法、访问静态字段等)时触发类加载,随后执行静态初始化块和静态变量赋值;实例变量在每次 new 对象时初始化,执行顺序为:父类实例变量 → 父类构造器 → 子类实例变量 → 子类构造器。
- 静态变量只初始化一次,即使创建 100 个对象,也只有一份且只初始化一回
- 实例变量每 new 一次就分配一次、初始化一次,互不影响
- 未显式赋值的静态变量和实例变量都会按类型默认初始化(如 int 为 0,Object 为 null)
访问方式与作用域限制
静态变量可通过类名.变量名直接访问,也可通过对象引用访问(不推荐,易误导);实例变量只能通过已存在的对象引用访问,不能用类名直接调用。
- 静态方法内部不能直接访问实例变量(因为可能没有对象存在),必须传入或创建对象后才能访问
- 实例方法可以自由访问静态变量和本对象的实例变量
- static 修饰的变量不能访问 this,因为它不属于任何特定实例
典型误用与注意事项
常见陷阱包括:在多线程环境下误将非线程安全的对象设为静态变量(如 SimpleDateFormat)、用静态变量保存用户会话数据导致串扰、或误以为“static final 常量”在编译期就完全内联(仅基本类型和字符串字面量满足)。
- public static List
cache = new ArrayList(); —— 多个线程同时 add 可能引发 ConcurrentModificationException - private static Random rand = new Random(); —— 安全,Random 本身线程安全
- 避免用静态变量持有 Activity、Context 等 Android 组件引用,防止内存泄漏
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











