Skip to content
第 19 / 250 章后端⏱ 10 分钟阅读

第 19 章:static 与 final 关键字

学习目标

  • 掌握 static 修饰字段、方法、代码块、内部类
  • 掌握 final 修饰类、方法、变量
  • 理解 static 初始化顺序(高频面试题)

一、static 关键字

1.1 static 字段(类变量)

java
public class User {
    private static int count = 0;     // ① 类变量:所有对象共享

    private String name;

    public User(String name) {
        this.name = name;
        count++;                       // ② 每创建一个对象 +1
    }

    public static int getCount() {    // ③ 静态方法访问静态字段
        return count;
    }
}

new User("A");
new User("B");
new User("C");
System.out.println(User.getCount());  // 3

类变量 vs 实例变量

维度类变量(static)实例变量
存储位置方法区堆(对象内)
共享所有对象共享每个对象独立
访问User.countuser.name

1.2 static 方法(类方法)

java
public class MathUtils {
    public static int max(int a, int b) {       // ① 静态方法
        return a > b ? a : b;
    }
}

MathUtils.max(3, 5);   // ✅ 通过类名直接调用,无需 new

静态方法的特点

java
public class Demo {
    private int instanceField = 10;
    private static int staticField = 20;

    public static void staticMethod() {
        System.out.println(staticField);     // ✅ 访问静态字段
        // System.out.println(instanceField); // ❌ 不能访问实例字段
        // instanceMethod();                  // ❌ 不能调用实例方法
    }

    public void instanceMethod() {
        System.out.println(staticField);     // ✅ 实例方法可访问静态
        System.out.println(instanceField);   // ✅
    }
}

原因:静态方法在类加载时存在,实例方法 / 字段要等对象创建才存在。

1.3 static 代码块(静态初始化块)

java
public class Config {
    private static final Properties PROPS = new Properties();

    static {                                    // ① 类加载时执行一次
        try {
            PROPS.load(new FileInputStream("config.properties"));
            System.out.println("配置文件加载完成");
        } catch (IOException e) {
            throw new RuntimeException("加载配置失败", e);
        }
    }
}

1.4 static 初始化顺序(高频面试题)

java
public class InitOrder {
    private static String staticField = initStaticField();
    private String instanceField = initInstanceField();

    static {
        System.out.println("2. 静态代码块");
    }

    {
        System.out.println("4. 实例代码块");
    }

    public InitOrder() {
        System.out.println("5. 构造器");
    }

    private static String initStaticField() {
        System.out.println("1. 静态字段初始化");
        return "static";
    }

    private String initInstanceField() {
        System.out.println("3. 实例字段初始化");
        return "instance";
    }

    public static void main(String[] args) {
        new InitOrder();
        new InitOrder();
    }
}

输出

1. 静态字段初始化
2. 静态代码块
3. 实例字段初始化
4. 实例代码块
5. 构造器
3. 实例字段初始化
4. 实例代码块
5. 构造器

1.5 static 内部类

java
public class Outer {
    private static int outerStatic = 10;

    public static class Inner {                  // ① 静态内部类
        public void hello() {
            System.out.println("outerStatic = " + outerStatic);  // ✅ 可访问外部静态字段
        }
    }
}

Outer.Inner inner = new Outer.Inner();          // ② 直接 new,无需外部实例

二、final 关键字

2.1 final 变量(常量)

java
public class Constants {
    public static final int MAX_COUNT = 100;       // ① 全局常量
    public static final String APP_NAME = "TaskFlow";

    private final String name;                     // ② 实例常量
    private final int id;

    public Constants(String name, int id) {
        this.name = name;
        this.id = id;
    }

    public void test() {
        final int localConst = 10;                 // ③ 局部常量
        // localConst = 20;                       // ❌ 不能修改
    }
}

final 变量的规则

java
// ❌ 错误:没有初始值
final int x;                  // 成员变量:构造器 / 初始化块 / 字段初始化中必须赋值
final int y;                  // 局部变量:使用前必须赋值

// ✅ 正确
final int z = 10;             // 声明时初始化

2.2 final 方法(不可重写)

java
public class Parent {
    public final void hello() {                   // ① final 方法
        System.out.println("Parent");
    }
}

public class Child extends Parent {
    // @Override                                  // ❌ 编译报错:不能重写 final 方法
    // public void hello() { }
}

2.3 final 类(不可继承)

java
public final class String { ... }                // String 是 final 类
public final class Math { ... }

// public class MyString extends String { ... }  // ❌ 编译报错

2.4 final 参数

java
public void process(final int x) {              // ① 参数不可修改
    // x = 10;                                  // ❌ 编译报错
    System.out.println(x);
}

三、static final 常量

java
public class Constants {
    public static final int MAX_COUNT = 100;          // 编译时常量
    public static final String DEFAULT_NAME = "Anonymous";
    public static final double PI = 3.141592653589793;
}

命名规范:全大写 + 下划线分隔。

四、本章小结

要点关键
static 字段类变量,所有对象共享
static 方法类方法,不能访问实例成员
static 块类加载时执行一次
初始化顺序静态(字段→块)→ 实例(字段→块→构造器)
final 变量不可修改的常量
final 方法不可重写
final 类不可继承
static final全局常量

动手练习

练习 1:基础题

创建一个 Counter 类,用 static 字段统计创建的对象数量。

练习 2:进阶题

写出以下代码的初始化顺序:

java
class Parent {
    static { System.out.println("P-static"); }
    { System.out.println("P-init"); }
    public Parent() { System.out.println("P-ctor"); }
}

class Child extends Parent {
    static { System.out.println("C-static"); }
    { System.out.println("C-init"); }
    public Child() { System.out.println("C-ctor"); }
}

// new Child();

下一章第 20 章:抽象类

本站基于 VitePress 构建 · 由 Codebook 团队维护