[英]calling a java constructor of same class from non static context leads to recursion but with static it works fine?
我试图了解Java类的初始化顺序。 特别是何时和以什么顺序是静态的,并且实例初始化器/字段被执行。 我想出了这个stackoverflow Question中的示例。 为什么在自我构造函数调用中添加static会阻止代码进入递归。
public class Test {
public static void main(String a[]) {
Cons1 c1 = new Cons1();
}
}
class Cons1 {
static Cons1 c = new Cons1(); /* if static is removed then recursion
occurs */
Cons1() {
//does something
}
}
静态上下文和实例上下文之间的行为差异是否存在任何特定原因。 我经历了Java文档的详细初始化过程 ,但是无法理解这种行为背后的逻辑是什么。 对JLS规范的任何解释或参考将很有帮助。
PS:我已经看过这个类似stackoverflow的帖子 ,但是我无法从那里得到答案。
如果将一个字段声明为static ,则无论该类最终会创建多少实例(可能为零), 都只存在该字段的一种形式 。 在初始化类时(第12.4节),将实现一个静态字段(有时称为类变量)。
另一方面,
如果声明符用于实例变量 (即非静态字段),则以下规则适用于其初始化程序:
- 在运行时, 每次创建该类的实例时,都会评估初始化器并执行分配。
让我们添加一个println
语句以查看整个图片:
class Cons1 {
static Cons1 c = new Cons1();
Cons1() {
System.out.println("the constructor was called");
}
public static void main(String[] args) {
Cons1 c1 = new Cons1();
Cons1 c2 = new Cons1();
}
}
它输出三次“调用了构造函数”:
1-加载类并初始化静态字段c
;
2-创建c1
时;
3-创建c2
时。
现在,我们将其与带有实例字段的示例进行比较:
class Cons1 {
Cons1 c = new Cons1();
Cons1() {
System.out.println("the constructor was called");
}
public static void main(String[] args) {
Cons1 c1 = new Cons1();
}
}
显然,它失败,并且下一个stacktrace不输出任何内容:
Exception in thread "main" java.lang.StackOverflowError
at Cons1.<init>(Cons1.java:33)
...
at Cons1.<init>(Cons1.java:33)
原因是Cons1
每个实例Cons1
需要另一个Cons1
对象。 因此,我们在调用栈中溢出了Cons1.<init>
方法。 结果,当堆栈达到其最大允许大小时,我们最终会遇到异常。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.