Java中的静态变量(Static Variables)的赋值时机主要分为以下几种情况:
1. **声明时初始化**:
静态变量可以在声明的同时进行初始化赋值,这也是最常见的赋值时机。一旦类被加载到JVM中,静态变量就会被初始化。
```java
public class MyClass {
public static int myStaticVar = 10; // 在类加载时初始化为10
}
```
2. **静态初始化块中初始化**:
如果静态变量的初始化需要复杂的逻辑,可以使用静态初始化块(Static Initialization Block)。静态初始化块会在类第一次被加载时执行,而且只会执行一次。
```java
public class MyClass {
public static int myStaticVar;
static {
myStaticVar = calculateValue(); // 在静态初始化块中赋值
}
}
```
3. **通过代码显式赋值**:
你可以在类加载后任何时刻通过类名直接访问静态变量并为其赋值,但这通常不被推荐,除非有特殊需要。
```java
public class MyClass {
public static int myStaticVar;
}
// 在类加载后的某个时刻
MyClass.myStaticVar = someComputation();
```
总的来说,静态变量的赋值发生在类的加载过程中,具体是:
- 在类加载期间,JVM会按照源代码中的顺序执行静态变量的初始化语句和静态初始化块。
- 静态变量的初始化在类的任何实例化之前完成,并且在类加载后直至JVM停止前一直存在。
需要注意的是,如果静态变量之间存在相互依赖关系,Java虚拟机保证它们的初始化顺序是根据源代码中的顺序进行的。
对于Java中声明为`static final`的变量,也就是静态常量(Static Constants),其赋值时机和规则更为特殊:
1. **编译时常量(Compile-Time Constant Expressions)**:
- 如果`static final`变量是基本类型或String类型,并且其值在声明时就可以明确计算出来(例如字面量或简单的算术运算结果),那么Java编译器会将其视为编译时常量。这种情况下,变量的值在编译阶段就已经确定,并且会内嵌到使用它的各个地方,无需等到运行时再去初始化。
```java
public static final int PI = 3.14; // 编译时常量,值在编译时就已知
public static final String COMPANY_NAME = "ACME Inc."; // 同样是编译时常量
```
2. **非编译时常量**:
- 如果`static final`变量的值无法在编译时确定(例如,它的值是从方法调用、文件读取或者其他不确定来源获取的),那么这个变量会在类加载的过程中初始化,具体是在类初始化的静态初始化块执行之前或在首次访问该变量时(如果还没有初始化的话)进行初始化赋值。一旦赋值后,其值就固定不变了。
```java
public static final int NUM_USERS;
static {
NUM_USERS = Database.countUsers(); // 在类加载时初始化
}
```
总结来说,`static final`变量的赋值时机取决于其值是否为编译时常量。若是编译时常量,赋值发生在编译阶段;若不是,则赋值发生在类加载时。无论何时赋值,赋值后其值都将不可改变。