3

对象作为类变量导致stackoverflow

public class stack {
        stack obj = new stack();   // its obvious that during class loading obj will call class to
        // load and infinite loop will occur. 
}

可以说我正在static从类 obj 中使用

public class stack {
      static stack obj = new stack();  // it will not cause infinite loop and program will //execute successfully
}

当类被JVM第一次捕获时(据我所知),静态变量被分配到内存中。仅当 JVM 开始将内存分配给上述static对象变量时才说在第一次。它将再次实习生调用该类,这也应该导致无限循环。某处我错了。有人可以突出我错在哪里。

4

5 回答 5

6

不,将其声明为static不会导致无限循环。这就是为什么。

静态变量在类加载期间初始化。因此,当您的类第一次加载时,编译器将为静态变量创建一个实例,仅此而已。这不会导致您的课程再次加载。由于您的课程没有再次加载,因此不会重复此过程。

如果您将其声明为非静态属性,那么情况就完全不同了。考虑一下 -

public class stack {
    stack obj = new stack();

    ........
}

此声明等效于 -

public class stack {
   stack obj;

    public stack() {
        obj = new stack();    // implicitly moved here by the compiler
    }

    ........
}

从最后一个示例中,很明显为什么这里存在无限递归。您正在stack其自己的构造函数中创建该类的一个实例,该实例又创建另一个,然后是另一个,......并且它继续下去,导致堆栈溢出。

于 2013-08-31T11:49:38.927 回答
0

加载“stack”类将导致创建“stack”的一个实例,将stack类保存为静态字段。那么,堆栈类的这个实例就没有什么要加载的了:没有堆栈异常。

于 2013-08-31T11:54:13.843 回答
0

关键字静态与无限循环无关。可以声明字段、方法、类(静态内部类)

静态字段:-首次加载类时创建和初始化静态字段。当引用类的静态成员或创建类的实例时会发生这种情况,以先到者为准。

静态方法:-使用 static 关键字声明的方法。与静态字段一样,静态方法与类本身相关联,而不是与从该类创建的任何特定对象相关联。因此,您不必在使用类定义的静态方法之前从类中创建对象。

最著名的静态方法是 main,Java 运行时调用它来启动应用程序。main 方法必须是静态的,这意味着应用程序默认在静态上下文中运行。

内存透视:-由于类被加载一次,其定义存储在 jvm 的 permgen 区域中,静态变量也存储在那里,将在 jvm 的生命周期中存在。

于 2013-08-31T11:59:47.493 回答
0

当类被JVM第一次捕获时,静态变量被分配到内存中

不完全是。

加载类时分配静态变量。

静态变量初始化在类初始化时执行。这可能会在类加载后的某个时间发生。

仅在 JVM 开始将内存分配给上述静态对象变量时才说。它将再次实习生调用该类,这也应该导致无限循环。

不,这是错误的,原因有两个:

  • 一般来说,对象不是“被拘留的”。实习是对String对象的操作,即便如此,它也只会对字符串文字自动发生。非文字字符串对象只有在您的应用程序String.intern() 显式调用它们时才会被实习。

  • 即使自动执行某种实习,也不会导致无限循环。您似乎认为实习会以某种方式导致重新启动或重复类初始化。这不可能发生,JVM 竭尽全力确保每个类在其生命周期内最多初始化一次。

于 2013-08-31T12:07:31.210 回答
0

在调试中我们可以了解到,当第一次控制静态变量时,由于变量只是类的一个实例,它会调用类加载。

然后控制进入类,并找到一个静态变量 object ,但此时它将由 JVM 分配一个内存地址值(与其他静态变量一样)。控制只是忽略变量作为实例,它假设纯粹是静态的并且程序继续。

于 2013-08-31T12:12:18.317 回答