Java static关键字

April 07, 2024 作者: southern 分类: 浏览: 1 评论: 0

static 是 Java 中的一个关键字,主要用于修饰 变量、方法、代码块内部类,作用是将成员定义为类级别,即属于类本身,而不是某个具体的实例对象。这里介绍一下static的主要用法和特点。

1. static 变量

  • 由类共享,所有对象访问的都是同一块内存,不因为对象不同而改变。

  • 在类加载时就被分配内存,生命周期与类一致。

  • 存储在方法区(JDK8 之后是元空间 Metaspace)。


class Student {
    static int totalStudents = 0; // 静态变量,所有对象共享
    String name;
​
    Student(String name) {
        this.name = name;
        totalStudents++; // 每创建一个 Student 对象,计数 +1
    }
​
    void display() {
        System.out.println(name + ",当前总学生数:" + totalStudents);
    }
}
​
public class Main {
    public static void main(String[] args) {
        Student s1 = new Student("Alice");
        Student s2 = new Student("Bob");
​
        s1.display(); // Alice,当前总学生数:2
        s2.display(); // Bob,当前总学生数:2
    }
}

2. static 方法

  • 无需创建对象即可调用,可以通过类名.方法名() 直接调用。

  • 不能访问非静态成员(非静态变量、非静态方法),非静态成员属于实例,而static 方法属于类。

  • 不能使用 thissuper 关键字, this 代表当前实例,而 static 方法不依赖实例。

class MathUtil {
    static int square(int x) {
        return x * x;
    }
}
​
public class Main {
    public static void main(String[] args) {
        int result = MathUtil.square(5); // 直接用类名调用
        System.out.println("5 的平方是:" + result);
    }
}

3. static 代码块

  • 类加载时执行且只执行一次。

  • 用于初始化静态变量或执行类级别的初始化操作。

class Database {
    static String url;
​
    // 静态代码块
    static {
        url = "jdbc:mysql://localhost:3306/test";
        System.out.println("静态代码块执行,数据库 URL 初始化完成!");
    }
}
​
public class Main {
    public static void main(String[] args) {
        System.out.println(Database.url); // 访问静态变量,触发类加载
    }
}

4. static 内部类

  • 静态内部类不依赖外部类对象,可以直接创建。

  • 不能访问外部类的非静态成员,但可以访问静态成员。

class Outer {
    static class Inner {
        void show() {
            System.out.println("我是静态内部类的方法");
        }
    }
}
​
public class Main {
    public static void main(String[] args) {
        Outer.Inner inner = new Outer.Inner(); // 直接创建内部类对象
        inner.show();
    }
}

public class Test extends Base{
​
    static{
        System.out.println("test static");
    }
​
    public Test(){
        System.out.println("test constructor");
    }
​
    public static void main(String[] args) {
        new Test();
    }
}
​
class Base{
​
    static{
        System.out.println("base static");
    }
​
    public Base(){
        System.out.println("base constructor");
    }
}

执行顺序解析

  1. 类加载阶段(static 代码块执行)

    • 程序从 main() 方法开始执行,此时 Test 还未被加载,因此 需要先加载 Test 类。

    • 由于 Test 继承自 Base,必须先加载 Base

    • 加载 Base 类,发现Base类有静态代码块,执行Base类的静态代码块

    • 加载 Test 类,发现Test类有静态代码块,执行Test类的静态代码块

  2. 创建对象阶段(构造方法执行)

    • main() 方法执行 new Test();,开始实例化 Test 对象

    • 由于Test继承自Base,所以必须先调用 Base 的构造方法,然后调用Test的构造方法

最终的输出顺序

base static
test static
base constructor
test constructor


#2024(13)

评论