堆栈溢出java

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
public class stack {
      static stack obj = new stack();  // it will not cause infinite loop and program will //execute successfully
}

当JVM第一次捕获类时,静态变量将分配到内存中(据我所知)。 例如,在第一次分配内存给上述static对象变量时。它会再次调用类,这应该也会导致无限循环。但是我可能有错误,能否有人指出我的错误所在。

5个回答

6
不,将变量声明为static不会导致无限循环。原因如下: static变量在类加载时被初始化。当你的类第一次加载时,编译器会为static变量创建一个实例,这就是全部了。这不会导致你的类再次加载。由于你的类没有再次加载,因此这个过程不会重复。
如果你将它声明为非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类的一个实例,而该实例又在其自身的构造函数中创建了另一个实例,接着又创建了另一个实例......如此反复,导致堆栈溢出。


0

加载“stack”类将导致创建一个实例作为静态字段保存在堆栈类中。然后,这个堆栈类的实例没有任何需要加载的内容:没有堆栈异常。


0

关键字“Static”与无限循环没有任何关系。您可以声明字段、方法、类(静态内部类)。

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

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

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

内存角度:由于类只加载一次并将其定义存储在JVM的permgen区域中,因此静态变量也存储在那里,并将在JVM的生命周期内保留。


0
静态变量在类第一次被JVM捕获时分配到内存中。
不完全正确。
静态变量在类加载时分配。
静态变量初始化是在类初始化时执行的。这可能会在类加载后的某个时间发生。
如果JVM开始为上述静态对象变量分配内存,则仅在第一次期间说。它将再次调用该类,这也应该导致无限循环。
不对。有两个原因:
1.总体上,对象不是“interned”。Interning是String对象上的操作,即使是这样,它只会自动发生在String字面值上。非文字字符串对象只有在应用程序在其上显式调用String.intern()时才会被interned。
2.即使自动执行了某种形式的interning,这也不会导致无限循环。您似乎认为interning会以某种方式导致类初始化重新启动或重复。这是不可能的,JVM会尽最大努力确保每个类在其生命周期内最多只初始化一次。

0

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

然后控制进入类,并找到一个静态变量对象,但此时JVM已经为其分配了内存地址值(与其他静态变量一样)。控制器仅将变量忽略为实例,并将其纯粹视为静态变量,程序继续运行。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接