Skip to content

12.1 static 静态关键字

static 关键字的概念

static 是 Java 中的一个关键字,用于修饰类、属性、方法和代码块。被 static 修饰的成员属于类,而不属于对象。

static 关键字的用途

1. 静态属性

静态属性(静态变量)是属于类的属性,所有对象共享同一个值。

语法:

java
[访问修饰符] static 数据类型 属性名 [= 初始值];

示例:

java
public class Student {
    private String name;
    private int studentId;
    // 静态属性,所有学生共享同一个学校名称
    public static String schoolName = "Java University";
    
    public Student(String name, int studentId) {
        this.name = name;
        this.studentId = studentId;
    }
    
    public String getName() {
        return name;
    }
    
    public int getStudentId() {
        return studentId;
    }
}

public class StaticExample {
    public static void main(String[] args) {
        Student student1 = new Student("John", 1001);
        Student student2 = new Student("Jane", 1002);
        
        System.out.println(student1.getName() + "'s school: " + Student.schoolName);
        System.out.println(student2.getName() + "'s school: " + Student.schoolName);
        
        // 修改静态属性,所有对象都会受到影响
        Student.schoolName = "Java Institute";
        System.out.println(student1.getName() + "'s school: " + Student.schoolName);
        System.out.println(student2.getName() + "'s school: " + Student.schoolName);
    }
}

2. 静态方法

静态方法是属于类的方法,可以直接通过类名调用,不需要创建对象。

语法:

java
[访问修饰符] static 返回类型 方法名([参数列表]) {
    // 方法体
}

示例:

java
public class MathUtils {
    // 静态方法,计算两个数的和
    public static int add(int a, int b) {
        return a + b;
    }
    
    // 静态方法,计算两个数的差
    public static int subtract(int a, int b) {
        return a - b;
    }
    
    // 静态方法,计算两个数的积
    public static int multiply(int a, int b) {
        return a * b;
    }
    
    // 静态方法,计算两个数的商
    public static double divide(int a, int b) {
        if (b == 0) {
            throw new IllegalArgumentException("除数不能为0");
        }
        return (double) a / b;
    }
}

public class StaticMethodExample {
    public static void main(String[] args) {
        // 直接通过类名调用静态方法
        int sum = MathUtils.add(5, 3);
        int difference = MathUtils.subtract(5, 3);
        int product = MathUtils.multiply(5, 3);
        double quotient = MathUtils.divide(5, 3);
        
        System.out.println("5 + 3 = " + sum);
        System.out.println("5 - 3 = " + difference);
        System.out.println("5 * 3 = " + product);
        System.out.println("5 / 3 = " + quotient);
    }
}

3. 静态代码块

静态代码块是在类加载时执行的代码块,用于初始化静态属性。

语法:

java
static {
    // 静态代码块
}

示例:

java
public class StaticBlockExample {
    // 静态属性
    public static int staticVar;
    public static String staticString;
    
    // 静态代码块
    static {
        System.out.println("静态代码块执行");
        staticVar = 100;
        staticString = "Hello, static block!";
    }
    
    public static void main(String[] args) {
        System.out.println("staticVar: " + staticVar);
        System.out.println("staticString: " + staticString);
    }
}

4. 静态内部类

静态内部类是被 static 修饰的内部类,可以直接通过外部类名访问。

示例:

java
public class OuterClass {
    private static int outerStaticVar = 100;
    private int outerInstanceVar = 200;
    
    // 静态内部类
    public static class StaticInnerClass {
        private int innerVar = 300;
        
        public void print() {
            // 可以访问外部类的静态变量
            System.out.println("outerStaticVar: " + outerStaticVar);
            // 不能访问外部类的实例变量
            // System.out.println("outerInstanceVar: " + outerInstanceVar);
            System.out.println("innerVar: " + innerVar);
        }
    }
    
    public static void main(String[] args) {
        // 直接通过外部类名创建静态内部类的对象
        OuterClass.StaticInnerClass inner = new OuterClass.StaticInnerClass();
        inner.print();
    }
}

static 关键字的特点

  1. 属于类:被 static 修饰的成员属于类,而不属于对象
  2. 内存分配:静态成员在类加载时分配内存,只分配一次
  3. 访问方式:静态成员可以通过类名直接访问,也可以通过对象访问
  4. 生命周期:静态成员的生命周期与类的生命周期相同
  5. 不能访问实例成员:静态方法不能直接访问实例属性和实例方法
  6. 不能使用 this 和 super:静态方法中不能使用 thissuper 关键字

示例:static 关键字的应用

示例 1:工具类

java
public class StringUtils {
    // 私有构造方法,防止创建对象
    private StringUtils() {
    }
    
    // 静态方法,判断字符串是否为空
    public static boolean isEmpty(String str) {
        return str == null || str.trim().isEmpty();
    }
    
    // 静态方法,反转字符串
    public static String reverse(String str) {
        if (isEmpty(str)) {
            return str;
        }
        StringBuilder sb = new StringBuilder(str);
        return sb.reverse().toString();
    }
    
    // 静态方法,截取字符串
    public static String substring(String str, int start, int end) {
        if (isEmpty(str)) {
            return str;
        }
        if (start < 0) {
            start = 0;
        }
        if (end > str.length()) {
            end = str.length();
        }
        if (start > end) {
            return "";
        }
        return str.substring(start, end);
    }
}

public class StringUtilsExample {
    public static void main(String[] args) {
        String str = "Hello, Java!";
        System.out.println("Original string: " + str);
        System.out.println("Is empty: " + StringUtils.isEmpty(str));
        System.out.println("Reversed: " + StringUtils.reverse(str));
        System.out.println("Substring (0, 5): " + StringUtils.substring(str, 0, 5));
    }
}

示例 2:计数器

java
public class Counter {
    // 静态属性,用于计数
    private static int count = 0;
    
    // 构造方法,每次创建对象时计数
    public Counter() {
        count++;
    }
    
    // 静态方法,获取计数
    public static int getCount() {
        return count;
    }
    
    // 静态方法,重置计数
    public static void resetCount() {
        count = 0;
    }
}

public class CounterExample {
    public static void main(String[] args) {
        System.out.println("Initial count: " + Counter.getCount());
        
        // 创建对象
        Counter counter1 = new Counter();
        System.out.println("After creating counter1: " + Counter.getCount());
        
        Counter counter2 = new Counter();
        System.out.println("After creating counter2: " + Counter.getCount());
        
        Counter counter3 = new Counter();
        System.out.println("After creating counter3: " + Counter.getCount());
        
        // 重置计数
        Counter.resetCount();
        System.out.println("After reset: " + Counter.getCount());
    }
}

示例 3:常量类

java
public class Constants {
    // 静态常量
    public static final double PI = 3.14159265358979323846;
    public static final int MAX_AGE = 150;
    public static final int MIN_AGE = 0;
    public static final String DEFAULT_NAME = "Unknown";
    
    // 私有构造方法,防止创建对象
    private Constants() {
    }
}

public class ConstantsExample {
    public static void main(String[] args) {
        System.out.println("PI: " + Constants.PI);
        System.out.println("MAX_AGE: " + Constants.MAX_AGE);
        System.out.println("MIN_AGE: " + Constants.MIN_AGE);
        System.out.println("DEFAULT_NAME: " + Constants.DEFAULT_NAME);
    }
}

常见问题

1. 在静态方法中访问实例成员

症状:编译错误:Cannot make a static reference to the non-static field fieldNameCannot make a static reference to the non-static method methodName()

解决方案:静态方法不能直接访问实例属性和实例方法,需要通过对象来访问

示例:

java
public class Example {
    private int instanceVar = 10;
    private static int staticVar = 20;
    
    // 实例方法
    public void instanceMethod() {
        System.out.println("instanceVar: " + instanceVar);
        System.out.println("staticVar: " + staticVar);
    }
    
    // 静态方法
    public static void staticMethod() {
        // 错误:不能直接访问实例变量
        // System.out.println("instanceVar: " + instanceVar);
        
        // 正确:可以访问静态变量
        System.out.println("staticVar: " + staticVar);
        
        // 错误:不能直接调用实例方法
        // instanceMethod();
        
        // 正确:通过对象调用实例方法
        Example example = new Example();
        example.instanceMethod();
    }
}

2. 在静态方法中使用 this 关键字

症状:编译错误:Cannot use this in a static context

解决方案:静态方法中不能使用 this 关键字,因为 this 表示当前对象,而静态方法属于类

示例:

java
public class Example {
    private static int staticVar = 10;
    
    // 错误:静态方法中不能使用 this
    // public static void staticMethod() {
    //     System.out.println(this.staticVar);
    // }
    
    // 正确:直接访问静态变量
    public static void staticMethod() {
        System.out.println(staticVar);
    }
}

3. 静态变量的初始化顺序

症状:静态变量的值不符合预期

解决方案:了解静态变量的初始化顺序:静态变量声明时的初始化 → 静态代码块中的初始化

示例:

java
public class InitializationOrder {
    // 静态变量声明时初始化
    public static int staticVar1 = 10;
    
    // 静态代码块
    static {
        staticVar1 = 20;
        staticVar2 = 30;
    }
    
    // 静态变量声明时初始化
    public static int staticVar2 = 40;
    
    public static void main(String[] args) {
        System.out.println("staticVar1: " + staticVar1); // 输出 20
        System.out.println("staticVar2: " + staticVar2); // 输出 40
    }
}

最佳实践

  1. 工具类使用静态方法:将工具类的方法设为静态,方便直接调用

  2. 常量使用静态 final:使用 static final 定义常量

  3. 合理使用静态变量:只在需要共享数据时使用静态变量

  4. 静态代码块的使用:用于初始化静态变量,特别是需要复杂初始化的情况

  5. 避免在静态方法中访问实例成员:静态方法应该只访问静态成员

  6. 私有构造方法:对于只包含静态方法的类,使用私有构造方法防止创建对象

总结

static 关键字是 Java 中的一个重要关键字,用于修饰类、属性、方法和代码块。被 static 修饰的成员属于类,而不属于对象。

static 关键字的主要用途:

  • 静态属性:所有对象共享同一个值
  • 静态方法:可以直接通过类名调用,不需要创建对象
  • 静态代码块:在类加载时执行,用于初始化静态属性
  • 静态内部类:可以直接通过外部类名访问

static 关键字的特点:

  • 属于类,不属于对象
  • 在类加载时分配内存,只分配一次
  • 可以通过类名直接访问
  • 生命周期与类的生命周期相同
  • 不能直接访问实例成员
  • 不能使用 thissuper 关键字

通过合理使用 static 关键字,可以提高代码的效率和可维护性。

© 2026 编程马·菜鸟教程 版权所有