static变量和方法属于类而非对象,因类加载时即在方法区分配内存并初始化,对象创建前已存在;所有实例共享同一份static成员,调用应通过类名而非对象;静态方法无法访问非静态成员,因无this且非静态成员依赖具体对象。

static变量和方法属于类,不是某个对象——这不是一句空话,而是由内存分配时机、共享机制和调用逻辑共同决定的。
类加载时就存在,对象还没出生
当你写 MyClass.count 或 MyClass.doWork(),JVM根本不需要你 new 一个 MyClass 实例。因为 static 成员在类被加载进方法区时,就已经分配内存并完成初始化了。而对象要等到执行 new 语句时,才在堆中创建。时间上,“类先活,对象后生”,所以 static 自然不属于任何具体对象。
所有对象共用同一份,不是每人一份
定义 public static int counter = 0; 后,哪怕创建 100 个 MyClass 实例:
- 内存里只有一个 counter,存放在方法区(不是堆,也不是栈)
- 无论哪个对象执行 obj1.counter++,其他所有对象看到的都是更新后的值
- 这和每个对象独有的 int id(非 static)完全不同——后者每个实例各占一份空间
调用方式直接体现归属关系
推荐写法就是直截了当:
- MyClass.VERSION —— 访问静态变量
- MyClass.parseJson(str) —— 调用静态方法
虽然语法上也允许 obj.staticMethod(),但编译器实际会把它“翻译”成 MyClass.staticMethod()。用对象去调 static,就像用快递员查国家邮政编码表——表本身属于邮政系统,不归哪个快递员管。
静态方法不能访问非静态成员,不是限制,是逻辑必然
因为:
- this 代表“当前对象”,但静态方法运行时可能压根没创建过任何对象
- 非静态变量和方法只存在于具体对象内部,没有对象,它们就不存在
- 编译器在编译阶段就禁止这种调用,不是运行时报错——它知道逻辑上不可能成立
- 反过来,非静态方法可以自由使用 static 成员,因为对象诞生时,类早已加载完毕,static 内容早就准备好了











