java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java static关键字常见误区

Java关键字static的6个常见误区及解决方法

作者:希望永不加班

文章主要讲述了Java中static关键字的常见误解和误区,包括static属于类而非对象、静态方法不能被重写、静态方法中不能使用this或super、静态代码块只会执行一次、static变量并非天生线程安全以及要在声明或静态块中初始化静态变量等内容,需要的朋友可以参考下

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. thissuper 代表当前实例对象

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. 在构造器、普通代码块给静态变量赋值:

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关键字常见误区的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文