rokevin
移动
前端
语言
  • 基础

    • Linux
    • 实施
    • 版本构建
  • 应用

    • WEB服务器
    • 数据库
  • 资讯

    • 工具
    • 部署
开放平台
产品设计
  • 人工智能
  • 云计算
计算机
其它
GitHub
移动
前端
语言
  • 基础

    • Linux
    • 实施
    • 版本构建
  • 应用

    • WEB服务器
    • 数据库
  • 资讯

    • 工具
    • 部署
开放平台
产品设计
  • 人工智能
  • 云计算
计算机
其它
GitHub
  • static 静态变量、类变量

  • 静态变量生命周期(类生命周期)
  • 静态变量、静态方法、静态代码块
    • 静态变量
    • 静态方法
    • 静态代码块
  • 1. 静态变量(类变量)
  • 2. 静态方法(类方法)
  • 3. 静态代码块(静态初始化块)
  • 4. 静态内部类
  • 5. 静态导入(Static Import)
  • 注意事项
  • 常见应用场景
  • 总结

static 静态变量、类变量

静态变量生命周期(类生命周期)

Static:

加载:java虚拟机在加载类的过程中为静态变量分配内存。

类变量:static变量在内存中只有一个,存放在方法区或堆,属于类变量,被所有实例所共享

销毁:类被卸载时,静态变量被销毁,并释放内存空间。static变量的生命周期取决于类的生命周期

类初始化顺序:

静态变量、静态代码块初始化

构造函数

自定义构造函数

结论:想要用static存一个变量,使得下次程序运行时还能使用上次的值是不可行的。因为静态变量生命周期虽然长(就是类的生命周期),但是当程序执行完,也就是该类的所有对象都已经被回收,或者加载类的ClassLoader已经被回收,那么该类就会从jvm的方法区卸载,即生命期终止。

更进一步来说,static变量终究是存在jvm的内存中的,jvm下次重新运行时,肯定会清空里边上次运行的内容,包括方法区、常量区的内容。

要实现某些变量在程序多次运行时都可以读取,那么必须要将变量存下来,即存到本地文件中。常用的数据存取格式:XML、JSON、Propertities类(类似map的键值对)等

静态变量、静态方法、静态代码块

类的生命周期分为装载、连接、初始化、使用和卸载的五个过程。

其中静态代码在类的初始化阶段被初始化。而非静态代码则在类的使用阶段(也是实例化一个类的时候)才会被初始化。

静态变量

可以将静态变量理解为类变量(与对象无关),而实例变量则属于一个特定的对象。

静态变量有两种情况:

• 静态变量是基本数据类型,这种情況 下在类的外部不必创建该类的实例可以直接使用

• 静态变量是一个引用。这种情况比较特殊,主要问题是由于静态变量是一个对象的引用,那么必须初始化这个对象之后才能将引用指向它。因此如果要把一个引用定义成static的,必须在定义的时候对其对象进行初始化。

public class TestStaticObject {

    static TestObject o = new Testobject(); //定义一个静态变量并实例化
    
    public static void main(String args[]){
        //在main中直接以“类名.静态变量名 方法名”的形式使用TestObject的方法
    } 
}

静态方法

与类变量不同,方法 (静态方法与实例方法) 在内存中只有一份,无论该类有多少个实例,都共用一个方法。

静态方法与实例方法的不同主要有:

• 静态方法可以直接使用 ,而实例方法必须在类实例化之后通过对象来调用。

• 在外部调用静态方法时,可以使用"类名.方法名"或者"对象名.方法名"的形式。实例方法只能使用后面这种方式。

• 静态方法只允许访问静态成员。而实例方法中可以访问静态成员和实例成员。

• 静态方法中不能使用this (因为this是与实例相关的)。

静态代码块

在java类中,可以将某一块代码声明为静态的。

static {
 //静态代码块中的语句
}

静态代码块主要用于类的初始化。它只执行一次,并在main函数之前执行。

静态代码块的特点主要有:

• 静态代码块会在类被加载时自动执行。

• 静态代码块只能定义在类里面,不能定义在方法里面。

• 静态代码块里的变量都是局部变量,只在块内有效。

• 一个类中可以定义多个静态代码块,按顺序执行。

• 静态代码块只能访问类的静态成员,而不允许访问实例成员。

在 Java 中,static 关键字用于修饰类的成员(字段、方法、内部类或初始化块),使其属于类本身,而非类的实例。下面详细解释其用法和作用:

1. 静态变量(类变量)

静态变量被类的所有实例共享,内存中只有一份拷贝,根据不同的版本,存储在方法区或者堆中。

字符串常量池和静态变量在内存中存储的位置

public class Student {
    private String name;
    public static int count = 0; // 静态变量,记录学生数量

    public Student(String name) {
        this.name = name;
        count++; // 每次创建实例时增加计数
    }
}

// 使用
Student s1 = new Student("Alice");
Student s2 = new Student("Bob");
System.out.println(Student.count); // 输出: 2

特点:

  • 通过类名直接访问:ClassName.staticVariable
  • 优先于对象存在,无需创建实例即可使用

2. 静态方法(类方法)

静态方法属于类,不依赖于任何实例,可直接通过类名调用。

public class MathUtils {
    public static int add(int a, int b) { // 静态方法
        return a + b;
    }
}

// 使用
int result = MathUtils.add(3, 5); // 无需创建 MathUtils 实例

限制:

  • 只能直接访问静态成员(静态变量和静态方法)
  • 不能使用 this 或 super 关键字(因为没有实例)

3. 静态代码块(静态初始化块)

用于类的静态变量初始化或执行类加载时的一次性操作,在类加载时执行一次。

public class Config {
    public static final String API_KEY;
    
    static { // 静态代码块
        // 从配置文件或环境变量读取 API_KEY
        API_KEY = System.getProperty("api.key", "default_key");
        System.out.println("API_KEY 已初始化");
    }
}

执行顺序:

  1. 静态变量声明和静态代码块按顺序执行
  2. 实例变量声明和实例初始化块按顺序执行
  3. 构造函数执行

4. 静态内部类

静态内部类不依赖于外部类的实例,可直接创建。

public class Outer {
    private static int x = 10;

    public static class StaticNested { // 静态内部类
        public void printX() {
            System.out.println(x); // 可访问外部类的静态成员
        }
    }
}

// 使用
Outer.StaticNested nested = new Outer.StaticNested();
nested.printX(); // 输出: 10

与非静态内部类的区别:

  • 静态内部类不能访问外部类的非静态成员
  • 创建时无需依赖外部类实例

5. 静态导入(Static Import)

用于导入类的静态成员,简化静态成员的调用。

import static java.lang.Math.PI;
import static java.lang.Math.sqrt;

public class Calculator {
    public static void main(String[] args) {
        double area = PI * 5 * 5; // 直接使用 PI,无需 Math.PI
        double root = sqrt(16);   // 直接使用 sqrt,无需 Math.sqrt
    }
}

注意事项

  1. 静态成员的生命周期 静态成员在类加载时创建,类卸载时销毁,生命周期长于实例对象。

  2. 静态方法不能被重写(Override) 静态方法属于类,子类可以定义同名静态方法,但这不是重写,而是隐藏父类的静态方法。

  3. 静态变量的线程安全 静态变量被多线程共享时可能存在线程安全问题,需使用同步机制(如 synchronized 或 Atomic 类)。

  4. 静态与实例的对比

    特性静态(static)实例(非 static)
    归属类对象
    访问方式类名.成员对象.成员
    内存分配方法区或堆(一份拷贝)堆(每个对象一份)
    生命周期类加载到卸载对象创建到销毁
    能否使用 this/super否是

常见应用场景

  • 工具类:如 java.lang.Math、java.util.Collections
  • 单例模式:通过静态变量保存唯一实例
  • 常量定义:使用 public static final 定义全局常量
  • 类加载时的初始化操作:如加载配置文件、初始化数据库连接池

总结

static 关键字的核心作用是将类的成员与类本身关联,而非与实例关联。合理使用 static 可以提高代码的效率(如工具类)和组织性(如常量定义),但需注意其生命周期和线程安全问题。

最近更新:: 2025/12/1 23:06
Contributors: luokaiwen