位置:首页 > Java > Java `static` 新手入门:从报错、共享变量到使用判断一次搞懂

Java `static` 新手入门:从报错、共享变量到使用判断一次搞懂

时间:2026-08-24  |  作者:实验室老王  |  阅读:0

目录

  1. 先看最常见的报错:为什么同一个类里也不能直接调用?
  2. `static` 到底表示什么:属于类,不属于某个对象
  3. 为什么有的变量互不影响,有的改一个全变?
  4. 什么时候该加 `static`,什么时候不该加?
  5. 静态代码块和几个高频问题,一次理顺

前言

刚接触 Java 时,很多人不是背不会 static 的定义,而是看见报错和运行结果时完全对不上号:明明方法写在同一个类里,为什么就是不能调?这篇文章不绕概念,先从最常见的报错和现象入手,再用变量共享、静态代码块和使用判断把 static 的边界讲清楚,帮你在写代码时判断它到底该不该加。

刚接触 Java 时,很多人不是背不会 static 的定义,而是看见报错和运行结果时完全对不上号:明明方法写在同一个类里,为什么就是不能调?这篇文章不绕概念,先从最常见的报错和现象入手,再用变量共享、静态代码块和使用判断把 static 的边界讲清楚,帮你在写代码时判断它到底该不该加。

先看最常见的报错:为什么同一个类里也不能直接调用?

很多新手第一次接触 static,往往是从一条 IDE 报错开始的:

静态上下文中不能直接调用实例方法的关系示意图
为什么 `main` 里不能直接调普通方法用“类上下文”和“对象上下文”的分层关系,解释为什么 `main` 里不能直接调用普通方法。
public class Student {
    private String name;

    public void sayHi() {
        System.out.println("Hi, " + name);
    }

    public static void main(String[] args) {
        sayHi(); // 直接爆红
    }
}

提示通常是:

Non-static method ‘sayHi()’ cannot be referenced from a static context

这句话的重点其实只有一个:你在 static 环境里,去调用了一个必须依赖对象的方法。

mainstatic 的,程序启动时可以直接执行它,不需要先创建某个 Student 对象;但 sayHi() 是普通方法,它属于某个具体对象。编译器并不知道你想调用的是谁的 sayHi(),所以会直接拒绝。

正确写法是什么?

先创建对象,再通过对象调用方法:

public static void main(String[] args) {
    Student s = new Student();
    s.sayHi(); // 这样才行
}

只要把这一步想清楚,很多 related 的报错都会顺下来:static 里不是“什么都不能调”,而是不能直接调依赖对象的成员。

`static` 到底表示什么:属于类,不属于某个对象

如果只记一句话,那就是:

static 是属于类的,不是属于某一个对象的。

这个定义看起来抽象,但换成更直观的理解会简单很多:

  • 加了 static 的成员,像班级公告栏,所有对象共享同一份
  • 没加 static 的成员,像每个人自己的笔记本,每个对象都有各自的数据

很多 Java 初学者卡住,并不是语法不会写,而是“类的公共信息”和“对象自己的信息”这两层概念没有分开。只要混在一起,就会在方法调用、变量修改和初始化顺序上不断踩坑。

为什么有的变量互不影响,有的改一个全变?

先看最常见的实例变量场景:

实例变量与静态变量的共享差异对比图
实例变量和静态变量怎么区分把 `name` 和 `schoolName` 放在同一张对比图里。
public class Student {
    String name;

    public Student(String name) {
        this.name = name;
    }
}
public class Main {
    public static void main(String[] args) {
        Student a = new Student("小明");
        Student b = new Student("小红");

        a.name = "Java 小明";

        System.out.println(a.name); // Java 小明
        System.out.println(b.name); // 小红
    }
}

为什么改了 a.nameb.name 不会跟着变?因为 name 没有加 static,它是实例变量。每创建一个对象,都会有自己单独的一份 name

但如果把变量改成静态成员,情况就不一样了:

public class Student {
    static String schoolName = "Java 大学";
    String name;

    public Student(String name) {
        this.name = name;
    }

    public void show() {
        System.out.println(name + " 来自 " + schoolName);
    }
}
public class Main {
    public static void main(String[] args) {
        Student a = new Student("小明");
        Student b = new Student("小红");

        a.show();
        b.show();

        // 直接通过类名修改
        Student.schoolName = "面向对象学院";

        System.out.println("----- 修改后 -----");

        a.show();
        b.show();
    }
}

输出:

小明 来自 Java 大学
小红 来自 Java 大学
----- 修改后 -----
小明 来自 面向对象学院
小红 来自 面向对象学院

这次两个对象看到的结果一起变了,因为 schoolName 只有一份,属于整个 Student 类。你改的不是某个对象自己的属性,而是所有对象共用的类级数据。

实际判断时怎么看?

像学校名、班级名、系统配置这类“大家共用一份”的信息,通常更适合写成 static。而学生姓名、年龄、成绩这种“每个对象各不相同”的数据,一般就应该保留为实例变量。

静态代码块执行时机与常见规则速览图
`static {}` 何时执行,常见规则怎把类加载、静态代码块执行、进入 `main` 的先后顺序。

什么时候该加 `static`,什么时候不该加?

和其死记硬背,不如写代码前先问自己三个问题:

1. 这个成员是不是只和类本身有关?

如果某个数据或方法表达的是整个类共享的规则、配置或工具能力,通常可以考虑 static

2. 它是不是必须依赖某个具体对象?

如果离开对象就说不清楚,比如“学生自我介绍”“打印当前姓名”,这类逻辑一般不该加 static

3. 这个数据是不是所有对象共享?

如果共享,就更接近静态成员;如果每个对象都应该各自保存一份,就应该用实例成员。

几类常见场景

  • 学校名、班级名、系统配置:通常适合 static
  • 学生姓名、成绩、年龄:通常不适合 static
  • 数学计算、工具方法:通常适合 static
  • 对象自己的行为,比如“自我介绍”:通常不适合 static

一句话概括就是:如果它是“类公共的”,就考虑 static;如果它是“对象私有的”,就别加。

静态代码块和几个高频问题,一次理顺

除了方法调用和变量共享,static 还有一个很容易让新手疑惑的点:为什么有些代码还没进 main 就先执行了?

public class Demo {
    static {
        System.out.println("静态代码块先执行");
    }

    public static void main(String[] args) {
        System.out.println("main 方法执行");
    }
}

输出:

静态代码块先执行
main 方法执行

原因在于 static {} 是静态代码块,它会在类第一次被加载时执行一次。程序运行某个类的 main、第一次使用该类的静态成员,或者第一次创建这个类的对象,都可能触发类加载。类先加载,再进入 main,所以它会先执行。

静态代码块一般用来做什么?

  • 加载配置
  • 初始化共享资源
  • 输出类加载相关信息

入门阶段先记住这一句就够了:static {} 是类加载时执行的,不是创建对象时执行的。

再看几个最常见的问题

Q1:static 方法能不能访问非 static 变量?
不能,除非你先创建对象,再通过对象访问。

Q2:非 static 方法能不能访问 static 变量?
可以,因为静态变量属于类,对象也能访问它。

Q3:static 方法能不能用 this?
不能。this 代表当前对象,而 static 方法不依赖对象。

Q4:static 方法能不能被重写?
不能真正重写。子类里写同名 static 方法,更准确地说叫隐藏,不是多态意义上的重写。

最后再避开三个常见误区

  • 误区一:认为 static 方法不能调用任何方法。实际上它可以调用其他 static 方法,只是不能直接调用非 static 方法。
  • 误区二:习惯性给所有方法都加 static。只要方法明显依赖对象状态,就不该这么写。
  • 误区三:把 static 理解成“静态、自动、固定不变”。入门时最稳妥的理解仍然是:它属于类。

很多人学 static 卡住,并不是这个知识点本身多复杂,而是刚开始学面向对象时,还没有把“类”和“对象”区分清楚。先盯住报错、运行结果和成员归属这三件事,理解会比死背定义快得多。

免责声明:文中图文均来自网络,如有侵权请联系删除,心愿游戏发布此文仅为传递信息,不代表心愿游戏认同其观点或证实其描述。

相关文章

更多

精选合集

更多

大家都在玩

热门话题

大家都在看

更多