Java关键字static的6个常见误区及解决方法
static 是 Java 入门最早接触、却也是误解最多的关键字。很多同学只会用它写静态常量、静态方法,但对生命周期、继承、重写、初始化顺序、this 能否使用、线程安全等认知模糊,日常写 Bug、面试翻车,大多都是踩了 static 的坑。
误区一:static 属于对象,而不是属于类
错误认知
静态变量、静态方法是归每个对象所有,创建越多实例,静态变量就有多份副本。
正确原理
1. static 修饰的成员,全局只一份,归属于类,不属于任何对象。
2. 类加载阶段就初始化,优先于对象存在,所有实例共享同一个静态变量。
3. 无论 new 多少个对象,静态变量内存中永远只有一份。
反例代码
public class StaticDemo {
public static int count = 0;
public StaticDemo(){
count++;
}
}连续 new 三次对象,count 直接累加到 3,而不是每个对象各自为 1。
结论
静态资源全局唯一、对象共享,跟实例数量无关。
误区二:静态方法可以被重写(Override)
错误认知
父类有静态方法,子类写一个同名同参静态方法,就是重写。
正确原理
1. 静态方法不能被重写,只能被隐藏(Hide)。
2. 静态方法编译期静态绑定,由引用类型决定调用哪个方法,而不是运行时对象类型。
3. 多态对 static 完全失效。
示例对比
class Father{
public static void show(){
System.out.println("父类静态方法");
}
}
class Son extends Father{
public static void show(){
System.out.println("子类静态方法");
}
}
public class Test{
public static void main(String[] args) {
Father f = new Son();
f.show(); // 输出:父类静态方法
}
}如果是普通实例方法,会走多态调用子类;静态方法看引用类型,不看实际对象。
结论
静态方法只可隐藏、不可重写,不具备多态特性。
误区三:静态方法中可以直接使用 this、super
错误认知
普通方法能用 this,静态方法也能用 this 访问成员。
正确原理
1. this、super 代表当前实例对象。
2. 静态方法属于类,不需要对象就能调用,执行时可能根本没有实例。
3. 因此静态方法禁止使用 this、super,也不能直接调用普通实例方法、直接访问实例变量。
编译报错代码
public static void test(){
this.xxx(); // 编译直接报错
}结论
静态上下文与实例无关,不能出现任何对象相关关键字。
误区四:静态代码块只会执行一次,随便写都没问题
错误认知
静态代码块随时都会执行,或者每次 new 对象都会执行。
正确原理
1. 静态代码块:类加载时执行,全局只执行一次。
2. 执行时机早于构造器、早于普通代码块。
3. 只会在类首次被加载、主动使用时触发一次,后续 new 对象不再执行。
4. 坑:静态块里不要写耗时逻辑、数据库连接、死循环,会直接拖慢项目启动、导致卡死。
执行顺序
静态代码块 → 普通代码块 → 构造方法
结论
静态块随类加载只跑一次,适合初始化常量、加载配置,禁止写耗时业务逻辑。
误区五:static 变量天然线程安全
错误认知
静态变量全局只有一份,自带同步,多线程修改也不会有并发问题。
正确原理
1. static 只是全局共享一份内存,不具备任何原子性、可见性、有序性保障。
2. 多线程同时读写静态变量,依然会出现脏数据、覆盖丢失、竞态条件。
3. 静态变量反而更容易引发并发 Bug,因为所有线程共享同一份。
并发错误示例
public class CountUtil{
public static int num = 0;
public static void add(){
num++;
}
}多线程循环累加,结果一定小于预期,典型线程不安全。
正确做法
静态变量并发修改需要:synchronized / AtomicInteger / Lock 保证线程安全。
结论
static ≠ 线程安全,共享变量反而更容易出并发问题。
误区六:可以在普通代码块/构造器中给静态变量随意初始化
错误认知
静态变量在哪赋值都一样,构造器、普通代码块随便改。
正确原理
1. 静态变量属于类,本该在:静态代码块、声明处初始化。
2. 在构造器、普通代码块给静态变量赋值:
- 每 new 一次对象,就会重新覆盖静态值;
- 极易造成全局状态被意外篡改,隐藏极深的 Bug。
3. 违背设计语义:静态资源不该依赖实例创建来初始化。
坑示例
public class User{
public static String type;
public User(){
type = "user";
}
}只要 new 一次,就强行覆盖静态变量,全局状态被随意改动。
结论
静态变量尽量在声明或静态块初始化,不要在构造器、实例代码块中赋值。
全文总结
这 6 个误区,既是日常开发高频坑,也是 Java 面试常问原题。
1. static 归类不归对象,全局唯一共享;
2. 静态方法不可重写、只能隐藏,无多态;
3. 静态上下文不能用 this / super,不能直接访问实例成员;
4. 静态代码块类加载仅执行一次,禁止耗时逻辑;
5. static 变量不自带线程安全,多线程必须加同步;
6. 静态变量尽量静态环境初始化,不要在构造器中乱赋值。
以上就是Java关键字static的6个常见误区及解决方法的详细内容,更多关于Java static关键字常见误区的资料请关注脚本之家其它相关文章!
相关文章
Mybatis中ResultMap解决属性名和数据库字段名不一致问题
我们Pojo类的属性名和数据库中的字段名不一致的现象时有发生,本文就详细的介绍一下Mybatis中ResultMap解决属性名和数据库字段名不一致问题,感兴趣的可以了解一下2021-10-10


最新评论