核心概念:一句话总结
- 实例变量:属于对象的变量,每个对象都有一套独立的副本,互不影响,它描述了对象的状态。
- 静态变量:属于类的变量,整个类只有一份共享的副本,所有对象共享这一份,它描述了类的状态。
详细对比表格
| 特性 | 实例变量 | 静态变量 |
|---|---|---|
| 所属 | 属于对象(实例) | 属于类 |
| 内存分配 | 当创建对象时,在堆内存中为该对象分配一份。 | 当类被加载到方法区时,就分配一份,存储在方法区(或静态域)。 |
| 生命周期 | 随着对象的创建而诞生,随着对象的被垃圾回收而消失。 | 随着类的加载而诞生,随着类的卸载而消失(通常与 JVM 生命周期相同)。 |
| 存储位置 | 堆内存中的对象内部。 | 方法区(在 JDK 7 及之前是永久代,JDK 8 及之后是元空间)。 |
| 创建方式 | 通过 new 关键字创建对象时自动创建。 |
在类加载时由 JVM 自动创建。 |
| 访问方式 | - 对象名.变量名 (e.g., myStudent.name)- 类名.变量名 (不推荐,但编译通过) |
- 类名.变量名 (推荐,e.g., Student.schoolName)- 对象名.变量名 (不推荐,但编译通过) |
| 内存占用 | 每创建一个对象,就会在内存中增加一份实例变量的空间。 | 无论创建多少个对象,静态变量在内存中只有一份。 |
| 共享性 | 不共享,每个对象的实例变量都是独立的,修改一个不影响其他。 | 共享,所有对象访问的是同一份静态变量,一个对象修改了,其他对象都会看到。 |
| 用途 | 描述对象特有的属性,每个学生的姓名、年龄、学号都不同。 | 描述所有对象共有的属性,所有学生都来自同一个学校。 |
| 初始化 | 在构造方法执行时被初始化。 | 在类加载时被初始化,通常使用静态初始化块或直接在声明时赋值。 |
代码示例与图解
让我们用一个经典的 Student 类来演示。

public class Student {
// --- 实例变量 ---
// 每个学生都有自己的姓名和年龄
String name;
int age;
// --- 静态变量 ---
// 所有学生都共享同一个学校名称
static String schoolName = "清华大学";
// 构造方法,用于创建对象时初始化实例变量
public Student(String name, int age) {
this.name = name;
this.age = age;
System.out.println("创建了一个学生: " + this.name);
}
}
内存中的变化
假设我们执行以下代码:
public class Main {
public static void main(String[] args) {
System.out.println("学校名称: " + Student.schoolName); // 通过类名访问静态变量
Student student1 = new Student("张三", 20);
Student student2 = new Student("李四", 21);
System.out.println(student1.name + " 的学校是: " + student1.schoolName);
System.out.println(student2.name + " 的学校是: " + student2.schoolName);
// 修改静态变量的值
Student.schoolName = "北京大学";
System.out.println("学校改名后...");
System.out.println(student1.name + " 的学校现在是: " + student1.schoolName);
System.out.println(student2.name + " 的学校现在是: " + student2.schoolName);
}
}
内存示意图:
-
Student类加载时:schoolName(静态变量) 在方法区被创建并初始化为 "清华大学"。name和age(实例变量) 此时还不存在。
+-------------------------+ | 方法区 | | | | Student Class | | - schoolName: "清华大学" <-- 静态变量,只有一份 | - name: (不存在) <-- 实例变量模板 | - age: (不存在) <-- 实例变量模板 | | +-------------------------+ -
new Student("张三", 20)创建student1对象后:
(图片来源网络,侵删)- 在堆内存中为
student1分配空间。 - 为
student1创建自己的name和age实例变量,并赋值为 "张三" 和 20。
+-------------------------+ +-------------------------+ | 方法区 | | 堆内存 | | | | | | Student Class | | Student Object 1 | | - schoolName: "清华大学" |----->| - name: "张三" | | - name: (不存在) | | - age: 20 | | - age: (不存在) | | | | | +-------------------------+ +-------------------------+ - 在堆内存中为
-
new Student("李四", 21)创建student2对象后:- 在堆内存中为
student2分配空间。 - 为
student2创建自己的name和age实例变量,并赋值为 "李四" 和 21。 - 注意:
student2和student1共享方法区中的schoolName。
+-------------------------+ +-------------------------+ | 方法区 | | 堆内存 | | | | | | Student Class | | Student Object 1 | | - schoolName: "清华大学" |----->| - name: "张三" | | - name: (不存在) | | - age: 20 | | - age: (不存在) | | | | | +-------------------------+ +-------------------------+ | Student Object 2 | | - name: "李四" | | - age: 21 | | | +-------------------------+ - 在堆内存中为
-
执行
Student.schoolName = "北京大学";后:- 修改的是方法区中唯一的
schoolName变量。 student1和student2再访问schoolName时,都会得到 "北京大学"。
- 修改的是方法区中唯一的
生活中的例子
- 实例变量:想象一个汽车制造厂,每辆生产出来的汽车(对象)都有自己的颜色、车牌号(实例变量),你把一辆车的颜色从红色改成蓝色,不会影响其他任何一辆车的颜色。
- 静态变量:这个汽车制造厂的名字(静态变量),所有从这个厂生产出来的汽车都共享同一个厂名,如果你把厂名从“一汽”改成“东风”,那么所有已经出厂和未来出厂的汽车,其“制造厂”属性都变成了“东风”。
何时使用?
使用实例变量:
当一个属性的值对于每一个对象都是不同的时候,就应该定义为实例变量。
Person类中的name,age,gender。BankAccount类中的balance,accountNumber。Car类中的currentSpeed,licensePlate。
使用静态变量:
当一个属性的值对于所有对象都是相同,或者需要在所有对象之间共享数据的时候,就应该定义为静态变量。

Math类中的PI(所有实例共享的常量)。Student类中的schoolName(所有学生共享的学校)。- 一个工具类中用来记录创建了多少个实例的计数器(
instanceCount)。
| 实例变量 | 静态变量 | |
|---|---|---|
| 归属 | 对象 | 类 |
| 数量 | N个对象,N份 | 1个类,1份 |
| 修改影响 | 只影响当前对象 | 影响所有对象 |
| 访问 | 对象名.变量名 | 类名.变量名 (推荐) |
记住这个核心区别:实例变量是“个人的”,静态变量是“大家的”,理解了这一点,你就能在大多数场景下正确地选择使用它们。
