你好,我想问下java中对象的初始化过程具体指什么,是怎样进行初始化的

1.栈溢出

2.public class A {
    A a = new A();
    public static void main(String[] args) {
        A a = new A();
    }
}

3.报错信息:

Exception in thread "main" java.lang.StackOverflowError

4.报错截图
图片描述

5.查了百度,但说的我都是一知半解的,他们都说是递归,导致栈溢出,可是构造器内并没有创建对象啊,我猜测应该是成员变量的加载和对象的初始化过程的问题:
相关链接:http://www.oschina.net/questi...

阅读 3.2k
5 个回答
public class A {
    A a = new A();
    public static void main(String[] args) {
        A a = new A();
    }
}

上面这段代码编译成字节码在翻译回来就像下面这样:

public class A {
    public A(){
        A a = new A();//这里重复调用了自己
    }
    public static void main(String[] args) {
        A a = new A();
    }
}

最简单的回答应该是每次new A()时都会创建一个对象。

下面分析一下稍微详细一点的过程
1.程序执行后首先进入main函数,然后第一次执行new A();
2.由于没有显示的构造函数,编译器在编译的时候会生成一个无参构造函数

 public A(){
 }

3.进入上面的构造函数后先要初始化成员变量,也就是 A a = new A();
4.这里就到的问题的关键,成员变量A初始化还是new A()继续调用2中的构造函数。
5.接着就会重复2、3、4的步骤,直到这个线程的栈空间不够用,抛出StackOverflowError错误。

这里还要普及一点方法调用的知识,在JVM中,每个线程都会分配一定的栈空间(非共享),这个栈空间可以是固定的可以是动态扩展的,不同的JVM这里的实现方式可以不同。线程中每执行一个方法,这个方法就会以栈帧的形式压入线程栈中。

上面出现StackOverflowError就是因为一直不断的调用构造方法,然后一直创建栈帧压入线程栈,最后栈空间不够用,导致栈溢出。

变量的初始化和内存中的运行机制

成员变量的初始化和内存中的运行机制

当系统加载类或创建该类的实例时,系统自动为成员变量分配内存空间,并在分配内存空间后,自动为成员变量指定初始值。

局部变量的初始化和内存中的运行机制

局部变量定义后,必须经过显式初始化后才能使用,系统不会为局部变量执行初始化。这意味着定义局部变量后,系统并未为这个变量分配内存空间,直到等到程序为这个变量赋初始值时,系统才会为局部变量分配内存,并将初始值保存到这块内存中。

正确的代码

public class A 
{
    public static void main(String[] args) 
    {
        A a = new A();
    }
}

java.lang.StackOverflowError异常

java.lang.StackOverflowError就是内存溢出,出现死循环;题主不应该在A类里创建A类的实例,A()相当于一个无参构造器,在A类里直接写A a = new A();会导致无限迭代地创建实例,最后导致内存溢出;错误提示也写明程序在第4行处出现错误,而且反复循环地出现错误

知识补充

欢迎题主来我主页学习Java知识并交流指导,关于题主所提及的知识点在我主页的Java面向对象(上)有提及:https://segmentfault.com/a/11...

楼上两位已经解释的很清楚了,简单的说就是你为类A增加了一个自身的实例变量a,这本身没什么问题,但是你将a的初始化放在了实例初始化的过程中,这样的话只要调用一次new A()就会进去一个无限调用的循环,所以就栈溢出了。

非常明显的递归调用,而且没有结束条件,肯定就内存溢出。递归就是方法里调用方法本身,而你给出的案例特殊一点,是构造方法,原因就是这么简单。

推荐问题
宣传栏