英文:
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);
}
}
}
}
My Query is: If for the input 1
, i.e., when the static final (constant) value of a class Example
is requested in another class Use
, then from where is that constant value fetched if the class Example
was never loaded into the JVM till then?
When and how was the static final i
initialized and stored into the JVM memory?
英文:
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);
}
}
}
}
When I run with java -verbose:class Use
, and give input as 1
then output is 10
i.e the constant i
value. But Example
class is not loaded yet.
However, when I give input as 2
, only then Example
class is loaded into the JVM, as visible by the verbose output, and then static block inside Example is executed and also j
's value initialized and then printed.
My Query is: If for the input 1
i.e when the static final (constant) value of a class Example
is requested in another class Use
, then from where is that constant value fetched if the class Example
was never loaded into the JVM till then?
When and how was the static final i
intialized and store into the JVM memory?
答案1
得分: 2
根据Java语言规范第12.4.1节(已添加强调):
在以下任何情况的第一次出现之前,将立即初始化类或接口类型T:
T是类,并创建了T的实例。
通过T声明的静态方法被调用。
由T声明的静态字段被赋值。
使用了由T声明的静态字段且该字段不是常量变量(§4.12.4)。
常量变量是用常量表达式初始化的final变量。在您的代码中,Example.i
是常量变量,因此不会导致类被加载。
因此,如果类没有被加载,值从何而来?
语言规范要求编译器将其值内联。来自二进制兼容性13.1节:
- 对于常量变量(§4.12.4)的字段引用必须在编译时解析为常量变量初始化器表示的值V。
如果此类字段是静态的,则在二进制文件中不应存在对字段的引用,包括声明字段的类或接口。该字段必须始终表现为已初始化(§12.4.2);绝不能观察到字段的默认初始值(如果与V不同)。
英文:
According to the Java language specification section 12.4.1 (emphasis added):
> 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).
A constant variable is a final variable that is initialized with a constant expression. In your code, Example.i
is a constant variable, and therefore does not cause the class to be loaded.
So if the class is not loaded, where does the value com from?
The language specification requires the compiler to inline its value. From section of binary compatibility 13.1:
> 3. 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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论