杰瑞科技汇

静态变量和实例变量到底有啥区别?

核心概念:一句话总结

  • 实例变量:属于对象的变量,每个对象都有一套独立的副本,互不影响,它描述了对象的状态。
  • 静态变量:属于的变量,整个类只有一份共享的副本,所有对象共享这一份,它描述了类的状态。

详细对比表格

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

代码示例与图解

让我们用一个经典的 Student 类来演示。

静态变量和实例变量到底有啥区别?-图1
(图片来源网络,侵删)
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);
    }
}

内存示意图:

  1. Student 类加载时

    • schoolName (静态变量) 在方法区被创建并初始化为 "清华大学"。
    • nameage (实例变量) 此时还不存在。
    +-------------------------+
    |      方法区             |
    |                         |
    |  Student Class          |
    |  - schoolName: "清华大学"  <-- 静态变量,只有一份
    |  - name: (不存在)        <-- 实例变量模板
    |  - age: (不存在)         <-- 实例变量模板
    |                         |
    +-------------------------+
  2. new Student("张三", 20) 创建 student1 对象后

    静态变量和实例变量到底有啥区别?-图2
    (图片来源网络,侵删)
    • 在堆内存中为 student1 分配空间。
    • student1 创建自己的 nameage 实例变量,并赋值为 "张三" 和 20。
    +-------------------------+      +-------------------------+
    |      方法区             |      |      堆内存              |
    |                         |      |                         |
    |  Student Class          |      |   Student Object 1      |
    |  - schoolName: "清华大学"  |----->|   - name: "张三"         |
    |  - name: (不存在)        |      |   - age: 20             |
    |  - age: (不存在)         |      |                         |
    |                         |      +-------------------------+
    +-------------------------+
  3. new Student("李四", 21) 创建 student2 对象后

    • 在堆内存中为 student2 分配空间。
    • student2 创建自己的 nameage 实例变量,并赋值为 "李四" 和 21。
    • 注意student2student1 共享方法区中的 schoolName
    +-------------------------+      +-------------------------+
    |      方法区             |      |      堆内存              |
    |                         |      |                         |
    |  Student Class          |      |   Student Object 1      |
    |  - schoolName: "清华大学"  |----->|   - name: "张三"         |
    |  - name: (不存在)        |      |   - age: 20             |
    |  - age: (不存在)         |      |                         |
    |                         |      +-------------------------+
    +-------------------------+      |   Student Object 2      |
                                   |   - name: "李四"         |
                                   |   - age: 21             |
                                   |                         |
                                   +-------------------------+
  4. 执行 Student.schoolName = "北京大学";

    • 修改的是方法区中唯一的 schoolName 变量。
    • student1student2 再访问 schoolName 时,都会得到 "北京大学"。

生活中的例子

  • 实例变量:想象一个汽车制造厂,每辆生产出来的汽车(对象)都有自己的颜色、车牌号(实例变量),你把一辆车的颜色从红色改成蓝色,不会影响其他任何一辆车的颜色。
  • 静态变量:这个汽车制造厂的名字(静态变量),所有从这个厂生产出来的汽车都共享同一个厂名,如果你把厂名从“一汽”改成“东风”,那么所有已经出厂和未来出厂的汽车,其“制造厂”属性都变成了“东风”。

何时使用?

使用实例变量:

当一个属性的值对于每一个对象都是不同的时候,就应该定义为实例变量。

  • Person 类中的 name, age, gender
  • BankAccount 类中的 balance, accountNumber
  • Car 类中的 currentSpeed, licensePlate

使用静态变量:

当一个属性的值对于所有对象都是相同,或者需要在所有对象之间共享数据的时候,就应该定义为静态变量。

静态变量和实例变量到底有啥区别?-图3
(图片来源网络,侵删)
  • Math 类中的 PI (所有实例共享的常量)。
  • Student 类中的 schoolName (所有学生共享的学校)。
  • 一个工具类中用来记录创建了多少个实例的计数器(instanceCount)。

实例变量 静态变量
归属 对象
数量 N个对象,N份 1个类,1份
修改影响 只影响当前对象 影响所有对象
访问 对象名.变量名 类名.变量名 (推荐)

记住这个核心区别:实例变量是“个人的”,静态变量是“大家的”,理解了这一点,你就能在大多数场景下正确地选择使用它们。

分享:
扫描分享到社交APP
上一篇
下一篇