在 Java 学习中,static 关键字修饰的变量、方法属于类本身,而非单个对象。通过一个家族姓名的实战案例,拆解静态变量、静态方法的核心特性,掌握 static 的用法。

一、案例需求说明

我们有两个 Java 类:

  1. FamilyPerson:家庭成员类,包含静态姓氏 surname(所有家庭成员共享同一个姓氏)和实例姓名 name(每个成员独有的名字),提供静态方法设置姓氏、普通方法设置名字。
  2. MainClass:主程序类,创建父亲、两个儿子三个对象,通过代码实现统一修改家族姓氏单独设置成员名字,并打印验证效果。

需要填充三处【代码】,完成完整程序运行。

二、完整代码实现

1. FamilyPerson.java(成员类,无需修改)

这个类定义了家庭成员的属性和方法,核心是static 修饰的 surname

public class FamilyPerson {
    // 静态变量:所有FamilyPerson对象共享同一个姓氏
    static String surname;
    // 实例变量:每个对象独有的名字
    String name;

    // 静态方法:只能访问静态变量,用于设置家族姓氏
    public static void setSurname(String s){
        surname = s;
    }

    // 普通方法:可以访问静态变量+实例变量,用于设置个人名字
    public void setName(String s) {
        name = s;
    }
}

2. MainClass.java(主程序,填充三处代码)

public class MainClass {
    public static void main(String args[]) {
        //【代码 1】用类名 FamilyPerson 访问 surname,并为 surname 赋值:"李"
        FamilyPerson.surname = "李";

        FamilyPerson father,sonOne,sonTwo;
        father = new FamilyPerson();
        sonOne = new FamilyPerson();
        sonTwo = new FamilyPerson();

        //【代码 2】father 调用 setName(String s),并向 s 传递"向阳"
        father.setName("向阳");

        sonOne.setName("抗日");
        sonTwo.setName("抗战");

        // 第一次打印:姓氏统一为"李"
        System.out.println("父亲:"+father.surname+father.name);
        System.out.println("大儿子:"+sonOne.surname+sonOne.name);
        System.out.println("二儿子:"+sonTwo.surname+sonTwo.name);

        //【代码 3】father 调用 setSurName(String s),并向 s 传递"张"
        father.setSurname("张");

        // 第二次打印:姓氏统一修改为"张"
        System.out.println("父亲:"+father.surname+father.name);
        System.out.println("大儿子:"+sonOne.surname+sonOne.name);
        System.out.println("二儿子:"+sonTwo.surname+sonOne.name);
    }
}

3. 程序运行结果

父亲:李向阳
大儿子:李抗日
二儿子:李抗战
父亲:张向阳
大儿子:张抗日
二儿子:张抗战

三、核心知识点深度拆解

这道题的核心是Java 静态变量(类变量)和实例变量的区别,也是 static 关键字最核心的考点。

1. 静态变量(static 变量)vs 实例变量

特性 静态变量(static String surname) 实例变量(String name)
归属 属于类本身,不属于单个对象 属于每个对象单独拥有
内存存储 方法区,仅分配1 次内存 堆区,每个对象分配独立内存
访问方式 推荐:类名。变量名兼容:对象名。变量名 只能:对象名。变量名
共享性 所有对象共享同一个值 每个对象值独立,互不影响
生命周期 类加载时创建,程序结束时销毁 对象创建时创建,对象销毁时销毁

案例中的体现

  • 三个对象(father/sonOne/sonTwo)共享同一个surname,修改一次,所有对象的姓氏都会同步改变;
  • 三个对象的name独立存储,父亲是 "向阳",大儿子是 "抗日",互不干扰。

2. 静态方法(static 方法)的规则

  1. 静态方法只能直接访问静态变量 / 静态方法,不能直接访问实例变量(因为实例变量属于对象,静态方法属于类,类加载时对象还未创建);
  2. 访问方式:推荐用类名调用,也可以用对象名调用(本质还是类的方法,不推荐);
  3. 静态方法中不能使用this关键字(this 代表当前对象,静态方法不属于对象)。

案例中的体现

  • setSurname()是静态方法,只能修改静态变量surname
  • 代码 1 用类名.静态变量赋值(标准写法),代码 3 用对象名.静态方法赋值(兼容写法,不推荐)。

3. 代码填充的核心逻辑

  • 代码 1:静态变量属于类,必须用类名。变量名访问 → FamilyPerson.surname = "李";
  • 代码 2setName()是实例方法,必须用对象名。方法名调用 → father.setName("向阳");
  • 代码 3setSurname()是静态方法,用对象名调用 → father.setSurname("张");

4. 为什么修改姓氏后,所有成员都变了?

这是静态变量最关键的特性:共享性。当我们执行FamilyPerson.surname = "李"时,内存中只存了一个 "李";当执行father.setSurname("张")时,这个唯一的静态变量值被改为 "张",所有引用它的对象都会读取到最新值。

这就像家族的族谱姓氏,全家族共享一个,修改后所有人的姓氏同步更新,完美契合静态变量的设计初衷。

四、static 变量 / 方法的使用场景

  1. 共享数据:比如项目中的全局配置、家族姓氏、公司名称、常量值等;
  2. 工具方法:不需要创建对象就能调用的方法,比如Arrays.sort()Math.random(),都是静态方法;
  3. 单例模式:保证一个类只有一个对象,核心就是静态变量。

五、避坑指南

  1. 不要用对象名访问静态变量 / 方法:虽然语法不报错,但违背设计逻辑,可读性极差;
  2. 静态方法不能访问实例变量:如果在setSurname()中修改name,编译器会直接报错;
  3. 静态变量推荐直接用类名访问,实例变量必须用对象名访问。

总结

  1. 静态变量:类所有,共享一份内存,修改一处全局生效;
  2. 实例变量:对象所有,独立存储,互不干扰;
  3. 访问规则:静态资源用类名访问,实例资源用对象名访问;
  4. 核心特性:静态变量的共享性是解题和理解 static 的关键。

更多推荐