静态变量初始化顺序,Java
可能重复:静态变量初始化顺序,Java,java,static,Java,Static,可能重复: 当我运行这个代码时,答案是1,我想应该是2。 每个步骤的初始化顺序和k值是多少 公共类测试{ 静态{k=2;} 静态int k=1; 公共静态void main(字符串[]args){ 系统输出println(k); } } 编辑1:作为“k设置为默认值”的后续,那么为什么下一个代码不编译?出现错误“无法在定义字段之前引用它” 公共类测试{ 静态{System.out.println(k);} 静态int k=1; 公共静态void main(字符串[]args){ 系统输出p
当我运行这个代码时,答案是1,我想应该是2。 每个步骤的初始化顺序和k值是多少
公共类测试{
静态{k=2;}
静态int k=1;
公共静态void main(字符串[]args){
系统输出println(k);
}
}
编辑1:作为“k设置为默认值”的后续,那么为什么下一个代码不编译?出现错误“无法在定义字段之前引用它”
公共类测试{
静态{System.out.println(k);}
静态int k=1;
公共静态void main(字符串[]args){
系统输出println(k);
}
}
编辑2:因为一些我不知道的原因,当它的“Test.k”代替了“k”时,它会工作
谢谢你的回答。这将确保:D它们按照您编写它们的顺序执行。如果代码为:
public class Test {
static int k = 1;
static {k = 2;}
public static void main(String[] args) {
System.out.println(k);
}
}
然后输出变为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);
}
}
简短回答 当类的初始化开始时,
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);
}
}
根据,来自:
程序中的每个变量在使用其值之前必须有一个值:
- 每个类变量、实例变量或数组组件在创建时都会使用默认值进行初始化
0
,0.0d
,null
,false
,等等。)
因此,在初始化类之前(由于其中一个原因),变量将保存一个初始值
根据(这里只引用了有趣的步骤,重点是我的):
六,。
[…]然后,初始化接口的最终
类变量和字段,其值为编译时常量表达式(§8.3.2.1、§9.3.1、§13.4.9、§15.28)
[……]
九,。
接下来,按照文本顺序执行类的类变量初始值设定项和静态初始值设定项,或者执行接口的字段初始值设定项,就像它们是单个块一样
让我们看一下步骤6,其中有4个最终的
类变量:stat1
,str2
,秒
,惰性
由于10
是常量表达式,因此“sdfff”
也是常量表达式,并且由于执行顺序的原因,无法观察str2
和stat1
的初始值。为了进行观察,最早可以在步骤9中进行
second
的情况表明,当右侧不是编译时常量表达式时,其初始值是可见的
惰性
的情况不同,因为赋值是在静态块中完成的,因此在步骤9中发生-因此可以观察其初始值。(好吧,编译器会仔细检查lazy
是否只分配了一次)
在使用编译时常量表达式初始化最终类变量之后,执行静态块和其他初始化程序
从示例中可以看出,静态块和初始化是根据文本顺序进行的-通过使用
str
变量进行演示-首先将其打印为null
,然后打印为something
,然后是crap,首先,k将被指定为默认值,然后从顶部开始,将运行静态代码,分配2个,然后分配1个。然后调用main函数并打印出kstatic int k=1
实际上是static int k代码>声明,然后静态{k=1;}
@KennyTM是的,如果我像你粘贴的帖子那样运行它,我就会知道发生了什么。@nhahtdh会给k分配默认值吗?那么为什么这段代码没有混合:公共类Test{static{System.out.println(k);k=2;}static int k;公共静态void main(String[]args){System.out.println(k);}}}@Hoto:(使用Test.k
打印它)。我没有足够的知识来解释整个情况。From:1)最终字段将根据初始值设定项进行初始化2)静态初始值设定项和静态块将根据文本顺序运行(在运行块之前,静态字段将具有默认值)一个测试程序来演示我的观点:关于这一点,我的问题不是这个意思。我想要初始化的顺序和每个步骤中k的值。好的,我添加了一个更详细的解释。是的。。。但是现在你的答案有点混乱,XDK是否设置为默认值?这段代码不包括:公共类测试{static{System.out.println(k);k=2;}static int k;公共静态void main(String[]args){System.out.println(k);}}这段代码包括:公共类测试{static{System.out.println(Test.k);k=2;}static int k;公共静态void main(String[]args){System.out.println(k);}
@EJP:注意2个条件1)最终类变量和2)初始值设定项是编译时常量,这在步骤6中完成。这里没有矛盾。你甚至可以在ideone上查看该节目。