写 C 代码时把变量加上 static,同事说这样别的文件就看不见了;换到 Java,static 方法里又不能直接用 this。同一个关键字,在不同语言里管的事情不完全一样。

C 语言里的三种用法

修饰局部变量,变量只初始化一次,函数返回后内存不释放,下次调用还是上次的值。修饰全局变量,链接属性变成内部链接,其他源文件用 extern 也找不到。修饰函数,同样只在该文件内可见,适合写内部辅助函数。这三种用法都围绕存储期和可见性,跟「静态」两个字的中文意思关系不大。面试里问 static的作用,通常是想确认你分得清生命周期和可见性。C 里静态变量默认初始化为 0,普通局部变量不初始化就是随机值。

void count(void) { static int n = 0; n++; }

每次调用 count,n 都在原来的基础上加一,函数退出也不归零。多线程里这样写要注意竞争,静态变量是共享的。

C++ 的类静态成员

类里声明 static 成员变量,所有对象共用一份,定义要放在类外,C++17 之后可以用 inline 直接在类内初始化。静态成员函数没有 this 指针,只能访问静态成员。单例模式、计数器、工具函数经常这么写。静态局部变量在 C++11 之后还要求线程安全的初始化。头文件里写 static 函数,每个包含它的源文件各有一份,代码体积会变大。

Java 里的 static

静态变量属于类,用类名访问,所有实例共享。静态方法不能直接调用非静态成员,因为加载类的时候对象可能还不存在。静态代码块在类加载时执行一次,常用来初始化配置。main 方法必须是 static,JVM 调用它时还没有创建对象。静态导入可以把类里的静态成员直接引进来,少写类名。

几个容易混的点

  • static 不改变变量的作用域,只改变存储期或链接属性。
  • C 的静态局部变量不是全局变量,别的函数访问不到。
  • Java 的 static 方法里没有 this,别在里面写 this.xxx。
  • 静态变量常驻内存,大对象别随便声明成 static。

判断:需要跨对象共享、或者要限制文件内可见,就用 static;需要每个对象独立一份状态,就别加。