Mic*_*zyk 3 java initialization reference class loading
创建对类对象的引用是否会导致加载类?加载类时会初始化静态变量,所以考虑到以下代码,答案是否定的,我是对的吗?
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;
}
}
Run Code Online (Sandbox Code Playgroud)
代码没有输出.
将类的加载和初始化视为同一件事是一个常见的错误。
\nJava语言规范区分了
\n\n\n加载是指查找具有特定名称的类或接口类型的二进制形式的过程,可能是通过即时计算,但更常见的是通过检索以前由 Java 编译器从源代码计算的二进制表示形式,并构造,从该二进制形式,一个
\nClass对象来表示类或接口。
\n\n链接是获取类或接口类型的二进制形式并将其组合到 Java 虚拟机的运行时状态中以便执行的过程。类或接口类型始终在链接之前加载。
\n链接涉及三种不同的活动:符号引用的验证、准备和解析。
\n
\n\n类的初始化
\nstatic包括执行其初始化程序和类中声明的静态字段(类变量)的初始化程序。
\n接口的初始化包括执行接口中声明的字段(常量)的初始值设定项。
对于大多数情况,加载和链接的确切时间并不重要,因此规范为 JVM 实现提供有关确切时间的一些自由度是没有问题的。仅在错误情况下,例如,当类不存在或存在不兼容性(链接或验证错误)时,JVM 特定的差异才会显示出来,涉及Error抛出关联的确切时间。
因此,您的问题的目的不是加载,而是初始化,因为您正在查看类初始化程序的执行所产生的副作用static。
初始化的时间是精确定义的:
\n\n\n\xc2\xa712.4.1。初始化发生时
\n类或接口类型 T 将在第一次出现以下任一情况之前立即初始化:
\n\n
\n- \n
TT是一个类并创建了一个实例。- \n
static调用由 声明的方法T。- \n
static由声明的字段被T赋值。- \n
static使用由 声明的字段,T并且该字段不是常量变量 ( \xc2\xa74.12.4 )。- \n
T是顶级类 ( \xc2\xa77.6 ),并且执行词法嵌套在( \xc2\assertxa78.1.3 ) 中的语句 ( \xc2\xa714.10 )。T当一个类被初始化时,它的超类被初始化(如果它们之前没有被初始化),以及声明任何默认方法( \xc2\xa79.4.3 )的任何超接口( \xc2\xa78.1.5)(如果它们有之前没有被初始化)。接口的初始化本身不会导致其任何超级接口的初始化。
\n
因此,从规范中,您可以得出结论:局部变量的存在永远不会触发初始化。将非值分配给引用类型的变量时null,必须有该类型的先前实例化已触发其初始化。然而,未使用的局部变量没有影响。
当涉及到加载而不是初始化时,可能会存在细微的差异,如本场景所示。
\n是.调用类方法或实例化实例时,将调用静态初始化程序.
从您的示例中,您可以执行以下操作之一:
public static void main(String[] args) {
A a = new A();
}
Run Code Online (Sandbox Code Playgroud)
public static void main(String[] args) {
int f = A.f();
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
96 次 |
| 最近记录: |