在Java中运行构造函数代码之前是否初始化字段?
有人能解释一下下面程序的输出吗?我认为构造函数是在实例变量之前初始化的。所以我希望输出是“xzy”在Java中运行构造函数代码之前是否初始化字段?,java,constructor,initialization,Java,Constructor,Initialization,有人能解释一下下面程序的输出吗?我认为构造函数是在实例变量之前初始化的。所以我希望输出是“xzy” 如果您查看类文件的反编译版本 class X { Y b; X() { b = new Y(); System.out.print("X"); } } class Y { Y() { System.out.print("Y"); } } public class Z extends X { Y
如果您查看类文件的反编译版本
class X {
Y b;
X() {
b = new Y();
System.out.print("X");
}
}
class Y {
Y() {
System.out.print("Y");
}
}
public class Z extends X {
Y y;
Z() {
y = new Y();
System.out.print("Z");
}
public static void main(String args[]) {
new Z();
}
}
您可以发现实例变量y
在构造函数中移动,因此执行顺序如下
Z的构造函数
X
X
构造函数newy Y()
的第一行newy Y()中的第一行
Y
所有实例变量都是使用构造函数语句初始化的 正确的初始化顺序是:
参见章节。初始化顺序在JLS 12.5中规定: 1.首先,为新对象分配内存 2.然后将对象中的所有实例变量(包括此类及其所有超类中定义的实例变量)初始化为其默认值 3.最后,调用构造函数
为了澄清对static的误解,我将简单地引用这段代码:
public class Foo {
{ System.out.println("Instance Block 1"); }
static { System.out.println("Static Block 1"); }
public static final Foo FOO = new Foo();
{ System.out.println("Instance Block 2"); }
static { System.out.println("Static Block 2 (Weird!!)"); }
public Foo() { System.out.println("Constructor"); }
static public void main(String p[]) {
System.out.println("In Main");
new Foo();
}
}
令人惊讶的是,输出如下所示:
静态块1
实例块1
实例块2
建造师
静态块2(奇怪!!)
大体上
实例块1
实例块2
建造师
注意,我们有一个在两个实例{}
之后调用的静态{}
。这是因为我们在中间抛出构造函数,第一次调用构造函数时调用执行顺序。
我在做这个答案的时候发现了这个-
基本上,我们观察到这种情况:
我需要研究继承的混合,以及对super的显式和隐式调用,这将如何影响这一点,并将随着研究结果而更新。这可能与其他提供的答案类似,只是他们在静态初始化时弄错了 调用构造函数时,实例变量初始值设定项在构造函数主体之前运行。您认为下面程序的输出是什么
public class Tester {
private Tester internalInstance = new Tester();
public Tester() throws Exception {
throw new Exception("Boom");
}
public static void main(String[] args) {
try {
Tester b = new Tester();
System.out.println("Eye-Opener!");
} catch (Exception ex) {
System.out.println("Exception catched");
}
}
}
main方法调用Tester构造函数,该构造函数引发异常。您可能希望catch子句捕获此异常并打印捕获的异常。
但是如果你试着运行它,你
发现它没有这样做,并抛出了一个
StackOverflowerError
很好的解释@Arun p johny+1。实例变量的初始化被移动到构造函数中。至少没有对规范的另一个错误解释。它不完整,但有助于解释发生了什么。链接到JLS for Java 8:and同样是错误的——请看我对@ÓscarLópez的评论。请注意,static
并不是您所指文档部分的一部分。带有注释的另一篇文章已被删除-但我在一个补充回答中提供了详细信息以及示例代码。不是一个完整的答案-但至少强调了静态{}
案例。@YoYo这个答案与JLS一致:具体地说,关于您在答案中提到的执行,与第9项一致。如果您的实现不符合JLS,请将其报告为bug。混淆的是类和实例实例化是分开讨论的。我想这就留下了实现细节来说明两者如何混合;DR:类成员初始化中的new被隐式地放在构造函数的顶部。因此,您基本上是在试图显示构造函数将在控件到达抛出部分之前继续调用自己(因为行private Tester internalInstance=new Tester();)。我的理解正确吗?这是因为private static Foo instance=new Foo()代码>,在第二个静态块之前运行。事实上,它是第二个静态块,您标记的第二个实际上是第三个。这里不神秘。
public class Tester {
private Tester internalInstance = new Tester();
public Tester() throws Exception {
throw new Exception("Boom");
}
public static void main(String[] args) {
try {
Tester b = new Tester();
System.out.println("Eye-Opener!");
} catch (Exception ex) {
System.out.println("Exception catched");
}
}
}