实例初始化程序中的 StackOverflowError
StackOverflowError in Instance Initialiser
这个问题比较理论化。所以我有下面这组代码:
public class Test {
public static void main(String[] args) {
Test test = new Test();
}
{
System.out.println("Instance execution");
}
}
它编译并打印 "Instance Execution"。
但是当我尝试以这种方式执行其他方法时:
public class Test {
public static void main(String[] args) {
Test test = new Test();
}
{
System.out.println("Instance execution");
}
private void anotherMethod() {
System.out.println("Method execution");
}
{
Test test = new Test();
test.anotherMethod();
}
}
它给我这个错误:
Exception in thread "main" java.lang.WhosebugError
at Test.<init>(Test.java:15)
我完全相信这个错误有最简单的解释,但我的问题是,是构造函数引发了这个错误吗?或者只有系统方法可以这样执行?可执行实例初始化程序的整个方法对我来说是非常新的,所以任何帮助将不胜感激。谢谢
这个:
{
Test test = new Test();
test.anotherMethod();
}
是一个实例初始化块。每次创建 Test
实例时都会 运行s。在其中,您正在...创建一个新的 Test
实例,它自然会触发该块,然后创建一个新的 Test
实例,该实例会触发该块...您明白了。
is it the constructor that's throwing this error?
是实例初始化,没错。事实上,在幕后,编译器处理实例初始化块的方式是将该代码逐字复制到 class 中每个构造函数的开头(包括默认构造函数,如果您不提供默认值),就在对 super
的任何调用之后(如果没有明确的调用,则为默认值)。所以你可以说这是构造函数抛出错误,即使概念上,它是实例初始化,与构造函数本身不同。
Or only System methods can be executed this way?
不确定 "System methods," 是什么意思,但问题是每个实例的初始化块是 运行。如果你只想要 运行 一次,在 class 初始化时,你可以使用 static
初始化块:
public class Test {
public static void main(String[] args) {
Test test = new Test();
}
{
System.out.println("Instance execution");
}
private void anotherMethod() {
System.out.println("Method execution");
}
static // <==================
{
System.out.println("Class initialization"); // ***
Test test = new Test();
test.anotherMethod();
}
}
输出:
Class initialization
Instance execution
Method execution
Instance execution
(我们看到 "Instance execution" 两次,因为 main
中有一个 new Test
,static
初始化块中有另一个。)
但实际上,最简单的事情是将对 anotherMethod
的调用放在 main
中:
public class Test {
public static void main(String[] args) {
Test test = new Test();
test.anotherMethod();
}
{
System.out.println("Instance execution");
}
private void anotherMethod() {
System.out.println("Method execution");
}
}
输出
Instance execution
Method execution
问题是,您在构造函数中创建了一个 Test 对象,这将创建另一个 Test 对象,依此类推。而是使用
this.anotherMethod();
这个问题比较理论化。所以我有下面这组代码:
public class Test {
public static void main(String[] args) {
Test test = new Test();
}
{
System.out.println("Instance execution");
}
}
它编译并打印 "Instance Execution"。 但是当我尝试以这种方式执行其他方法时:
public class Test {
public static void main(String[] args) {
Test test = new Test();
}
{
System.out.println("Instance execution");
}
private void anotherMethod() {
System.out.println("Method execution");
}
{
Test test = new Test();
test.anotherMethod();
}
}
它给我这个错误:
Exception in thread "main" java.lang.WhosebugError
at Test.<init>(Test.java:15)
我完全相信这个错误有最简单的解释,但我的问题是,是构造函数引发了这个错误吗?或者只有系统方法可以这样执行?可执行实例初始化程序的整个方法对我来说是非常新的,所以任何帮助将不胜感激。谢谢
这个:
{
Test test = new Test();
test.anotherMethod();
}
是一个实例初始化块。每次创建 Test
实例时都会 运行s。在其中,您正在...创建一个新的 Test
实例,它自然会触发该块,然后创建一个新的 Test
实例,该实例会触发该块...您明白了。
is it the constructor that's throwing this error?
是实例初始化,没错。事实上,在幕后,编译器处理实例初始化块的方式是将该代码逐字复制到 class 中每个构造函数的开头(包括默认构造函数,如果您不提供默认值),就在对 super
的任何调用之后(如果没有明确的调用,则为默认值)。所以你可以说这是构造函数抛出错误,即使概念上,它是实例初始化,与构造函数本身不同。
Or only System methods can be executed this way?
不确定 "System methods," 是什么意思,但问题是每个实例的初始化块是 运行。如果你只想要 运行 一次,在 class 初始化时,你可以使用 static
初始化块:
public class Test {
public static void main(String[] args) {
Test test = new Test();
}
{
System.out.println("Instance execution");
}
private void anotherMethod() {
System.out.println("Method execution");
}
static // <==================
{
System.out.println("Class initialization"); // ***
Test test = new Test();
test.anotherMethod();
}
}
输出:
Class initialization Instance execution Method execution Instance execution
(我们看到 "Instance execution" 两次,因为 main
中有一个 new Test
,static
初始化块中有另一个。)
但实际上,最简单的事情是将对 anotherMethod
的调用放在 main
中:
public class Test {
public static void main(String[] args) {
Test test = new Test();
test.anotherMethod();
}
{
System.out.println("Instance execution");
}
private void anotherMethod() {
System.out.println("Method execution");
}
}
输出
Instance execution Method execution
问题是,您在构造函数中创建了一个 Test 对象,这将创建另一个 Test 对象,依此类推。而是使用
this.anotherMethod();