Java 静态成员浅析

静态变量

静态变量也称为类变量,类所有的实例都共享静态变量,可以直接通过类名来访问它,静态变量在内存中只存在一份。

在并发或后端接口的开发中,需要注意静态变量对于所有线程或用户都是共享的,可能会导致线程安全问题或互相影响,实现单个线程或用户拥有独立的静态变量,应使用 ThreadLocal 实现。

静态方法

静态方法是属于类的方法,不依赖于类的具体实例,而是直接通过类名来调用。静态方法在内存中只存在一份,无论类有多少个对象实例,它们共享相同的静态方法。由于静态方法不依赖于实例状态,通常用做定义工具函数。

首先回顾一下面向对象中的两个概念:

  1. 多态性:指同一方法调用可以根据调用的对象不同而表现出不同的行为。
  2. 重写:指子类在继承父类的方法时,对该方法进行重新定义,调用该方法时将执行子类的实现而不是父类的实现。【重写的本质是为了实现多态性。】

静态方法属于类而不属于对象实例,所以在继承关系中不会表现出多态性,于是我们可以容易得到:

  1. 静态方法不能被子类重写,因为重写的本质是多态性,而静态方法不支持多态性,所以静态方法不能被子类重写。
  2. 静态方法不能是抽象方法,因为其不能被继承,所以必须实现。

如下代码可以看到这里并没有实现重写,只是覆盖了父类的方法, childRef.staticMethod(); 调用的依然是父类的防范。不过之类通过对象去调用静态方法是一个不建议的行为。

class Parent {
    public static void staticMethod() {
        System.out.println("Parent's static method");
    }
}

class Child extends Parent {
    public static void staticMethod() {
        System.out.println("Child's static method");
    }
}

public class StaticMethodDemo {
    public static void main(String[] args) {
        Parent.staticMethod(); // Output: Parent's static method
        Child.staticMethod();  // Output: Child's static method

        Parent parentRef = new Parent();
        Parent childRef = new Child();

        parentRef.staticMethod(); // Output: Parent's static method
        childRef.staticMethod();  // Output: Parent's static method
    }
}

静态语句块

静态代码块是用于在类加载时执行的代码块,它在类的生命周期中只会执行一次。静态代码块通常用于进行一次性的初始化操作,例如加载配置文件、初始化静态变量等。

public class AppConfig {
    // 静态变量
    public static int staticVar1 = 10;
    
    // 静态变量和静态代码量会按照它们在代码中的顺序进行初始化。
    static {
        // 例如加载配置文件,初始化静态变量等
    }

    // 静态变量
    public static int staticVar2 = 10;
}

静态内部类

静态内部类(也称为嵌套静态类),它不依赖于外部类的实例,因此可以直接创建静态内部类的对象,无需先创建外部类的实例,理所当然的也就无法访问外部类的非静态的成员变量和方法。

public class OuterClass {
    // 外部类的成员和方法

    // 静态内部类
    public static class InnerStaticClass {
        // 静态内部类的成员和方法
    }
}

// 创建静态内部类的实例
OuterClass.InnerStaticClass inner = new OuterClass.InnerStaticClass();

加载顺序

它们都是在类加载时完成初始化的,也就是说,在类被首次使用之前,它们会被初始化。在 Java 中,在类加载和实例化过程中,遵循以下顺序:

  1. 父类(静态变量和静态语句块):首先,会初始化父类的静态变量和执行父类的静态语句块,按照它们在代码中的顺序进行初始化。
  2. 子类(静态变量和静态语句块):接着,会初始化子类的静态变量和执行子类的静态语句块,也是按照它们在代码中的顺序进行初始化。
  3. 父类(实例变量和普通语句块):在创建子类实例之前,会先执行父类的实例变量初始化和普通语句块。
  4. 父类(构造函数):然后调用父类的构造函数,完成父类实例的初始化。
  5. 子类(实例变量和普通语句块):接着,会执行子类的实例变量初始化和普通语句块。
  6. 子类(构造函数):最后调用子类的构造函数,完成子类实例的初始化。

你可能感兴趣的:(java,开发语言,静态成员,静态变量)