A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 祁振朋 中级黑马   /  2013-3-11 21:24  /  1925 人查看  /  7 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 祁振朋 于 2013-3-12 18:11 编辑

class Demo7
{
  Demo7 d=new Demo7();//会出现问题,相当于死循环,内存溢出了。
  public static void main(String[] args)
  {
   Demo7 dd=new Demo7();   
  }
}
老师讲了当时没有弄明白。所以请各位解答一下,为什么这个程序会是死循环,是溢出呢?

评分

参与人数 1技术分 +1 收起 理由
陈丽莉 + 1

查看全部评分

7 个回复

倒序浏览
本帖最后由 张学林 于 2013-3-11 22:22 编辑
  1. class Demo7 {
  2.         Demo7() {
  3.                 System.out.println(1);
  4.         }// 这里有个空参构造函数,当主函数调用之后,它就和下面那一句玩上了,就没有你啥事了

  5.         Demo7 d = new Demo7();// 会出现问题,相当于死循环,内存溢出了。

  6.         public static void main(String[] args) {
  7.                 Demo7 dd = new Demo7();
  8.         }
  9. }
复制代码
好像不对,坐等知情人解答
回复 使用道具 举报
你这个肯定得溢出呀,

class Demo7 {
       new Demo7();//对象在产生对象,你说会不会溢出!

评分

参与人数 1技术分 +1 收起 理由
陈丽莉 + 1

查看全部评分

回复 使用道具 举报
要明白这个问题 首先了解下 java中的内存分配      java中的内存大体分为两种  栈区+堆区  主要存放内容如下
基础数据类型直接在栈空间分配, 方法的形式参数,直接在栈空间分配,当方法调用完成后从栈空间回收。   引用数据类型,需要用new来创建,既在栈空间分配一个地址空间,又在堆空间分配对象的类变量 。 方法的引用参数,在栈空间分配一个地址空间,并指向堆空间的对象区,当方法调用完成后从栈空间回收。局部变量 new 出来时,在栈空间和堆空间中分配空间,当局部变量生命周期结束后,栈空间立刻被回收,堆空间区域等待GC回收。 方法调用时传入的 literal 参数,先在栈空间分配,在方法调用完成后从栈空间分配。字符串常量在 DATA 区域分配 ,this 在堆空间分配 。数组既在栈空间分配数组名称, 又在堆空间分配数组实际的大小!
注意以上红字部分  
在你的这段代码中
  Demo7 d=new Demo7();  这个d的变量地址便存放在栈区   那么你这个程序为什么会内存溢出呢  我运行了你的程序 报的是
java.lang.StackOverflowError
        at Demo7.<init>(Demo7.java:2)
at Demo7.<init>(Demo7.java:4)
        at Demo7.<init>(Demo7.java:4)
        at Demo7.<init>(Demo7.java:4)
        at Demo7.<init>(Demo7.java:4)
这么一个异常  StackOverflowError 即栈区内存溢出  说明栈区的内存被你的变量地址值占满了  为什么会出现这种情况呢
看下异常的第二行   在类初始化的时候报的   
再了解下java类初始化的流程
(静态变量、静态初始化块)-->(变量、初始化块)-->构造器
再看你的代码  Demo7 d=new Demo7();  这句话 即是初始化快  而这句话你又使用了new来创建一个类对象  而创建类对象又会继续执行这句话 这样就会产生无限递归调用  即会产生无限多的  d变量  
从而导致栈区溢出

评分

参与人数 1技术分 +1 收起 理由
陈丽莉 + 1

查看全部评分

回复 使用道具 举报
本帖最后由 付玉光 于 2013-3-11 22:52 编辑

class Demo7
{
   Demo7 d=new Demo7();//会出现问题,相当于死循环,内存溢出了。
  public static void main(String[] args)
  {
   Demo7 dd=new Demo7();   
   System.out.println(dd);
  }
}
{:soso_e100:}//来,让我给大家解决一下这个问题。

//在本类中有一个成员属性该成员属性是(本类的实例对象),这说明当我们在创建一个本类的实例对象后,

//该实例对象的成员属性中就也会有一个(本类的实例)这样下来,就产生了递归,而我们在定义递归时,

//通常要有递归结束的标记,如果没有递归结束标记(出口)的话,则会产生StackOverflowError异常。

//而当我们把本类中的成员属性 d 用static修饰后 ,就说明该成员属性是被本类的实例对象所共享的,它只随着类的加载创建一次,
//所以也就不会产生StackOverflowError异常了。

评分

参与人数 1技术分 +1 收起 理由
陈丽莉 + 1

查看全部评分

回复 使用道具 举报
这就是典型的递归思想的调用,但是,是没有返回值的,递归调用也是有止境的,我记得这我老师在上课教递归的时候表演过类似的,一旦递归调用超出了虚拟机分配的内存就溢出了。可惜具体递归调用的深度我忘了。
回复 使用道具 举报
如果没有问题了,请将分类改成【已解决】~
回复 使用道具 举报
谢谢各位的解答。谢谢了。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马