当我运行这段代码时答案是1,我认为它将是2.初始化的顺序和每一步中k的值是多少?
public class Test {
static {k = 2;}
static int k = 1;
public static void main(String[] args) {
System.out.println(k);
}
}
Run Code Online (Sandbox Code Playgroud)
编辑1:作为"k设置为默认值"的后续内容,为什么下一个代码不能编译?这是一个错误"无法在定义之前引用字段".
public class Test {
static {System.out.println(k);}
static int k=1;
public static void main(String[] args) {
System.out.println(k);
}
}
Run Code Online (Sandbox Code Playgroud)
编辑2:对于一些我不知道的原因,当^而不是"k"它的"Test.k"时它起作用.
感谢所有的答案.这将是完美的:D
它们按照您编写的顺序执行.如果代码是:
public class Test {
static int k = 1;
static {k = 2;}
public static void main(String[] args) {
System.out.println(k);
}
}
Run Code Online (Sandbox Code Playgroud)
然后输出变为2.
初始化的顺序是:..类的类变量初始化器和静态初始化器......,以文本顺序,就像它们是单个块一样.
并且值(对于您的代码)是:k = 0(默认值),然后将其设置为2,然后将其设置回1.
您可以通过运行以下代码来检查它是否实际设置为2:
private static class Test {
static {
System.out.println(Test.k);
k = 2;
System.out.println(Test.k);
}
static int k = 1;
public static void main(String[] args) {
System.out.println(k);
}
}
Run Code Online (Sandbox Code Playgroud)
简答
当类的初始化开始时,k初始值为 0。
然后执行静态块(因为它位于声明中的赋值之前),k并将被赋值为 2。
然后执行声明中的初始化程序,k并将被赋值为 1。
长解释
让我们使用这个例子,因为你的例子有点简单:
class TestInitOrder {
static {
System.out.println(TestInitOrder.stat1);
System.out.println(TestInitOrder.stat2);
System.out.println(TestInitOrder.str);
System.out.println(TestInitOrder.str2);
str = "something";
System.out.println(TestInitOrder.str);
System.out.println(TestInitOrder.str2);
System.out.println(TestInitOrder.lazy);
System.out.println(TestInitOrder.second);
}
private static final int stat1 = 10;
static final String str2 = "sdfff";
static String str = "crap";
private static int stat2 = 19;
static final Second second = new Second();
static final int lazy;
static {
lazy = 20;
}
static {
System.out.println(TestInitOrder.str2);
System.out.println(TestInitOrder.stat2);
System.out.println(TestInitOrder.str);
System.out.println(TestInitOrder.lazy);
System.out.println(TestInitOrder.second);
}
public static void main(String args[]) {
}
}
class Second {
public Second() {
System.out.println(TestInitOrder.second);
}
}
Run Code Online (Sandbox Code Playgroud)
根据Java Language Specification,来自第 4.12.5 节:
程序中的每个变量在使用它的值之前都必须有一个值:
- 每个类变量、实例变量或数组组件在创建时都使用默认值进行初始化
(从本说明书中的以下各行指定的默认值的所有类型,基本上某种形式的0,如0,0.0d,null,false,等等)
所以在类被初始化之前(由于这些原因之一),变量将保持一个初始值。
根据详细的初始化过程(这里只引用有趣的步骤,重点是我的):
6. [...] 然后,初始化其值为编译时常量表达式的接口的
final类变量和字段 (第 8.3.2.1 节、第 9.3.1 节、第 13.4.9 节、第 15.28 节)。[...]
9. 接下来,按文本顺序执行类的类变量初始值设定项和静态初始值设定项,或接口的字段初始值设定项,就好像它们是单个块一样。
让我们看看第 6 步,有 4 个final类变量:stat1, str2, second, lazy。
由于10是常量表达式,所以是"sdfff",并且由于执行的顺序,就不可能观察初始值str2和stat1。为了进行观察,您最早可以在步骤 9 中进行。
的情况下 second说明当右边不是一个编译时常量表达式,所以它的初始值是可见的。
的情况lazy不同,因为赋值是在静态块中完成的,因此发生在第 9 步 - 因此可以观察其初始值。(好吧,编译器仔细检查lazy只分配了一次)。
在使用编译时常量表达式初始化 final 类变量之后,将执行静态块和其余的初始化程序。
从示例中可以看出,静态块和初始化根据文本顺序发生 - 使用str变量进行演示- 它首先打印为null,然后something,然后crap。
| 归档时间: |
|
| 查看次数: |
12994 次 |
| 最近记录: |