class 是在声明其引用时加载的吗?
Is the class loaded when its reference is declared?
创建对 class 对象的引用是否会导致加载 class?
加载 class 时会初始化静态变量,因此考虑以下代码,答案是否定的,对吗?
class A{
static int f(){
System.out.println("initializing!");
return 0;
}
static final int i = f();
}
public class Main {
public static void main(String[] args) {
A a;
}
}
代码没有给出任何输出。
是的。当调用 class 方法或实例化实例时调用静态初始化器。
根据您的示例,您可以执行以下操作之一:
1。创建新实例
public static void main(String[] args) {
A a = new A();
}
2。调用静态 Class 方法
public static void main(String[] args) {
int f = A.f();
}
将 class 的加载和初始化视为同一件事是一个常见的错误。
-
Loading refers to the process of finding the binary form of a class or interface type with a particular name, perhaps by computing it on the fly, but more typically by retrieving a binary representation previously computed from source code by a Java compiler, and constructing, from that binary form, a Class
object to represent the class or interface.
-
Linking is the process of taking a binary form of a class or interface type and combining it into the run-time state of the Java Virtual Machine, so that it can be executed. A class or interface type is always loaded before it is linked.
Three different activities are involved in linking: verification, preparation, and resolution of symbolic references.
-
Initialization of a class consists of executing its static
initializers and the initializers for static fields (class variables) declared in the class.
Initialization of an interface consists of executing the initializers for fields (constants) declared in the interface.
在大多数情况下,加载和链接的准确时间并不重要,因此规范为 JVM 实现提供了一些关于准确时间的自由度是没有问题的。仅在错误的情况下,例如当 class 不存在或存在不兼容性(链接或验证错误)时,JVM 特定差异可能会出现,关于抛出关联 Error
的确切时间。
所以你的问题针对的不是 loading,而是 initialization 因为你正在查看由static
class 初始化器的执行。
初始化时间为precisely defined:
§12.4.1. When Initialization Occurs
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).
T
is a top level class (§7.6) and an assert
statement (§14.10) lexically nested within T
(§8.1.3) is executed.
When a class is initialized, its superclasses are initialized (if they have not been previously initialized), as well as any superinterfaces (§8.1.5) that declare any default methods (§9.4.3) (if they have not been previously initialized). Initialization of an interface does not, of itself, cause initialization of any of its superinterfaces.
因此,从规范中,您可以得出这样的结论:局部变量的存在永远不会触发初始化。将非 null
值分配给引用类型的变量时,必须存在已触发其初始化的该类型的先前实例化。但是,未使用的局部变量没有影响。
当谈到加载而不是初始化时,可能会有细微的差别,如图所示this scenario。
创建对 class 对象的引用是否会导致加载 class?
加载 class 时会初始化静态变量,因此考虑以下代码,答案是否定的,对吗?
class A{
static int f(){
System.out.println("initializing!");
return 0;
}
static final int i = f();
}
public class Main {
public static void main(String[] args) {
A a;
}
}
代码没有给出任何输出。
是的。当调用 class 方法或实例化实例时调用静态初始化器。
根据您的示例,您可以执行以下操作之一:
1。创建新实例
public static void main(String[] args) {
A a = new A();
}
2。调用静态 Class 方法
public static void main(String[] args) {
int f = A.f();
}
将 class 的加载和初始化视为同一件事是一个常见的错误。
-
Loading refers to the process of finding the binary form of a class or interface type with a particular name, perhaps by computing it on the fly, but more typically by retrieving a binary representation previously computed from source code by a Java compiler, and constructing, from that binary form, a
Class
object to represent the class or interface. -
Linking is the process of taking a binary form of a class or interface type and combining it into the run-time state of the Java Virtual Machine, so that it can be executed. A class or interface type is always loaded before it is linked.
Three different activities are involved in linking: verification, preparation, and resolution of symbolic references.
-
Initialization of a class consists of executing its
static
initializers and the initializers for static fields (class variables) declared in the class.
Initialization of an interface consists of executing the initializers for fields (constants) declared in the interface.
在大多数情况下,加载和链接的准确时间并不重要,因此规范为 JVM 实现提供了一些关于准确时间的自由度是没有问题的。仅在错误的情况下,例如当 class 不存在或存在不兼容性(链接或验证错误)时,JVM 特定差异可能会出现,关于抛出关联 Error
的确切时间。
所以你的问题针对的不是 loading,而是 initialization 因为你正在查看由static
class 初始化器的执行。
初始化时间为precisely defined:
§12.4.1. When Initialization Occurs
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 ofT
is created.- A
static
method declared byT
is invoked.- A
static
field declared byT
is assigned.- A
static
field declared byT
is used and the field is not a constant variable (§4.12.4).T
is a top level class (§7.6) and anassert
statement (§14.10) lexically nested withinT
(§8.1.3) is executed.When a class is initialized, its superclasses are initialized (if they have not been previously initialized), as well as any superinterfaces (§8.1.5) that declare any default methods (§9.4.3) (if they have not been previously initialized). Initialization of an interface does not, of itself, cause initialization of any of its superinterfaces.
因此,从规范中,您可以得出这样的结论:局部变量的存在永远不会触发初始化。将非 null
值分配给引用类型的变量时,必须存在已触发其初始化的该类型的先前实例化。但是,未使用的局部变量没有影响。
当谈到加载而不是初始化时,可能会有细微的差别,如图所示this scenario。