Are fields initialized before constructor code is run in Java?
有人能解释一下以下程序的输出吗?我认为构造函数是在实例变量之前初始化的。所以我希望输出是"XZYY"。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
正确的初始化顺序是:
参见JavaVirtualMealEngress规范的第2.2.5-6节。
如果您查看类文件的反编译版本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
您可以发现实例变量
所有实例变量都是使用构造函数语句初始化的。
当调用构造函数时,实例变量初始值设定项在构造函数主体之前运行。你认为下面程序的输出是什么?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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"); } } } |
主方法调用测试人员构造函数,这会引发异常。您可能期望catch子句捕获此异常并打印捕获的异常。但是如果你试着运行它,你发现它什么也不做,就扔了一个
为了澄清静态的误解,我将简单地引用这段代码:
1 2 3 4 5 6 7 8 9 10 11 12 | 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 2 3 4 5 6 7 8 9 | Static Block 1 Instance Block 1 Instance Block 2 Constructor Static Block 2 (Weird!!) In Main Instance Block 1 Instance Block 2 Constructor |
注意,我们有一个
当我研究这个答案时发现了这个-https://stackoverflow.com/a/30837385/744133。
基本上,我们观察到这种情况会发生:
在第一次初始化对象时,初始化静态和实例初始化的当前对象,根据发生顺序混合初始化
对于所有接下来的初始化,只按照发生顺序进行实例初始化,因为静态初始化已经发生。
我需要研究继承的混合,以及对super的显式和隐式调用,这将如何影响这一点,并将随着发现而更新。它可能与其他提供的答案类似,只是它们在静态初始化时出错了。
初始化顺序在JLS 12.5中规定:
1.首先,为新对象分配内存
2.然后对象中的所有实例变量(包括这个类中定义的变量及其所有超类)都初始化为它们的默认值。
3.最后调用构造函数。
https://stackoverflow.com/questions/26552799/which-run-first-default-values-for-instance-variables-or-super-constructors