我尝试了解通过引用同一封闭类对象初始化静态字段时初始化顺序的行为。
public class Test {
static final Test t=new Test();
static int a=5;
Test(){
System.out.println("a="+a);
}
public static void main(String[] args) {
new Test();
}
}
上面这段代码的输出是:
a=0
a=5
如果我将变量修改a
为除plain之外的其他任何内容static
:
static final a=5;
a=5;
final a=5;
输出为:
a=5
a=5
为什么会这样呢?
请注意,a=5 & a=5
即使同时t & a
声明了两者,输出也是如此,static final
在这种情况下t
,声明之前a
静态最终成员先于其他静态成员初始化。
非最终静态成员按出现顺序初始化
因此,在您的第一种情况下:
static Test t=new Test();
static int a=5;
构造函数在a
初始化之前首先被调用,因此a=0
被显示。
在第二种情况下,static final a
在之前初始化t
,因此a=5
在Test
创建的第一个实例时显示。如果a
不是静态的,则在执行构造函数之前对其进行初始化,因此再次a=5
显示。
关于您的问题中的编辑。
查看JLS的12.4.2节:
- 然后,初始化其最终值是 编译时常量表达式
的接口的最终类变量和字段(第8.3.2.1,第9.3.1,第13.4.9,第15.28节)。
…
- 接下来,以文本顺序执行类的类变量初始化器和静态初始化器,或接口的字段初始化器,就好像它们是单个块一样。
您会看到,仅当final类变量(即static
final)的值是编译时常量表达式时,它们才在其余静态变量之前初始化。5
是一个常量表达式。new Test()
不是。因此即使它们都是静态的final也会a
被初始化t
。
问题内容: 我正在尝试发现初始化发生的顺序,或者更确切地说,为什么要按此顺序进行初始化的原因。给定代码: 输出: 但是,将的声明移动到初始化块之前会产生: 而且我完全不知道为什么会以这种顺序发生。此外,如果我在的声明中消除了关键字,则init块和构造函数均不会触发。谁能帮我这个忙吗? 问题答案: 我认为您只是缺少JLS的12.4.2节,其中包括: 接下来,以文本顺序执行类的类变量初始化器和静态初始
问题内容: 好吧,所以说我有一个看起来像这样的课: 我可以依靠类加载器来按顺序初始化那些字段,以便我可以依靠SERVLET_LOGGER在signupObservableAgent之前实例化吗? 问题答案: 是的,它们按照它们在源中出现的顺序进行了初始化。您可以在Java语言规范§12.4.2中阅读所有详细内容。请参阅步骤9,内容为: …以文本顺序执行类的类变量初始值设定项和静态初始值设定项,或者
问题内容: 下面的程序打印: 首次加载类时,首先要初始化静态块和字段,然后才初始化实例块和字段。因此,应首先初始化变量“ objectName1”和“ objectName2”,然后初始化实例变量“ list”……但输出显然与该理论相矛盾……任何人都可以解释程序行为(我不是在批评程序)。设计本身顺便说一句)? 问题答案: 静态块 按顺序 初始化(因此您可以在下面的代码中依赖上面的代码)。通过在中创
静态字段何时初始化?如果我从未实例化过一个类,但我访问了一个静态字段,那么用于实例化私有静态字段的所有静态块和私有静态方法(按顺序)都在那一刻被调用了吗?或者什么时候启动应用程序?
问题内容: 当我运行此代码时,答案是1,我想应该是2。初始化的顺序和每一步中k的值是什么? 编辑1:作为后续的“ k设置为默认值”,那么为什么下一个代码不能编译?出现错误“在定义字段之前无法引用它”。 编辑2:出于某种我不知道的原因,它^可以在其“ Test.k”代替“ k”时使用。 感谢所有的答案。这将满足:D 问题答案: 它们按照您编写它们的顺序执行。如果代码是: 然后输出变为2。 初始化的顺
问题内容: 据我了解,“静态初始化块”用于设置静态字段的值(如果无法在一行中完成的话)。 但是我不明白为什么我们需要为此设置一个特殊的块。例如,我们将字段声明为静态(无值分配)。然后编写几行代码,生成并为上面声明的静态字段分配一个值。 为什么我们需要在这样一个特殊的块这样的行:? 问题答案: 在非静态块: 每次构造类的实例时被调用。在静态块只被调用一次,当类本身初始化,无论该类型的有多少对象创建。