Class 加载与初始化:Java static final 变量
Class Loading vs Initialisation: Java static final variable
Example.java
public class Example {
static final int i = 10;
static int j = 20;
static {
System.out.println("Example class loaded and initialized");
}
}
Use.java
import java.util.Scanner;
public class Use {
public static void main(String args[]){
Scanner sc = new Scanner(System.in);
int ch = 1;
while(ch != 0) {
System.out.print("Enter choice: ");
ch = sc.nextInt();
if (ch == 1) {
System.out.println("Example's i = " + Example.i);
} else if(ch == 2){
System.out.println("Example's j = " + Example.j);
}
}
}
}
当我 运行 和 java -verbose:class Use
时,输入为 1
则输出为 10
,即常量 i
值。但是 Example
class 还没有加载。
但是,当我将输入作为 2
时, 只有 Example
class 被加载到 JVM 中,如详细输出,然后执行 Example 中的静态块,并初始化并打印 j
的值。
我的查询是: 如果对于输入 1
即当 class Example
的静态最终(常量)值是在另一个 class Use
中请求,如果 class Example
直到那时才加载到 JVM 中,那么从哪里获取常量值?
static final i
何时以及如何初始化并存储到 JVM 内存中?
根据Java language specification section 12.4.1(重点添加):
A class or interface type T will be initialized immediately before
the first occurrence of any one of the following:
T is a class and an instance of T is created.
A static method declared by T is invoked.
A static field declared by T is assigned.
A static field declared by T is used and the field is not a constant variable (§4.12.4).
一个constant variable is a final variable that is initialized with a constant expression。在您的代码中,Example.i
是一个常量变量,因此不会导致加载 class。
所以,如果 class 没有加载,值 com 从哪里来?
语言规范要求编译器内联它的值。来自 binary compatibility 13.1 部分:
A reference to a field that is a constant variable (§4.12.4) must be
resolved at compile time to the value V denoted by the constant
variable's initializer.
If such a field is static, then no reference to the field should be
present in the code in a binary file, including the class or interface
which declared the field. Such a field must always appear to have been
initialized (§12.4.2); the default initial value for the field (if
different than V) must never be observed.
Example.java
public class Example {
static final int i = 10;
static int j = 20;
static {
System.out.println("Example class loaded and initialized");
}
}
Use.java
import java.util.Scanner;
public class Use {
public static void main(String args[]){
Scanner sc = new Scanner(System.in);
int ch = 1;
while(ch != 0) {
System.out.print("Enter choice: ");
ch = sc.nextInt();
if (ch == 1) {
System.out.println("Example's i = " + Example.i);
} else if(ch == 2){
System.out.println("Example's j = " + Example.j);
}
}
}
}
当我 运行 和 java -verbose:class Use
时,输入为 1
则输出为 10
,即常量 i
值。但是 Example
class 还没有加载。
但是,当我将输入作为 2
时, 只有 Example
class 被加载到 JVM 中,如详细输出,然后执行 Example 中的静态块,并初始化并打印 j
的值。
我的查询是: 如果对于输入 1
即当 class Example
的静态最终(常量)值是在另一个 class Use
中请求,如果 class Example
直到那时才加载到 JVM 中,那么从哪里获取常量值?
static final i
何时以及如何初始化并存储到 JVM 内存中?
根据Java language specification section 12.4.1(重点添加):
A class or interface type T will be initialized immediately before the first occurrence of any one of the following:
T is a class and an instance of T is created.
A static method declared by T is invoked.
A static field declared by T is assigned.
A static field declared by T is used and the field is not a constant variable (§4.12.4).
一个constant variable is a final variable that is initialized with a constant expression。在您的代码中,Example.i
是一个常量变量,因此不会导致加载 class。
所以,如果 class 没有加载,值 com 从哪里来?
语言规范要求编译器内联它的值。来自 binary compatibility 13.1 部分:
A reference to a field that is a constant variable (§4.12.4) must be resolved at compile time to the value V denoted by the constant variable's initializer.
If such a field is static, then no reference to the field should be present in the code in a binary file, including the class or interface which declared the field. Such a field must always appear to have been initialized (§12.4.2); the default initial value for the field (if different than V) must never be observed.