黑马程序员技术交流社区

标题: java.lang.StackOverflowError [打印本页]

作者: 丁朋伟    时间: 2011-9-21 08:34
标题: java.lang.StackOverflowError
挺郁闷的错,高手指点下
public class Person {

      Person person ;
       
          public static void main(String[] args){
                  Person a = new Person();
      }
          
          {
                  person = new Person ();
          }
          
          public Person(){
                  System.out.println(person);
          }
}
报错:Exception in thread "main" java.lang.StackOverflowError
作者: 匿名    时间: 2011-9-21 08:38
你的程序貌似有问题,再说你想写什么样的程序,怎么写成这样了,自己把自己搞了....

建议对java不太熟悉的话,就不要写这种没人写的程序来考研自己对java的理解程序,这样没多大意义,实际中谁也不会设计这样的程序。。。。
作者: 匿名    时间: 2011-9-21 08:47
小生在学习构造器初始化,出了点小问题,如果您解决不了,又耽误了您的时间我深感歉意
作者: 匿名    时间: 2011-9-21 08:58
package test;
public class Person {

      Person person;
        
          public static void main(String[] args){
                  Person a = new Person();
      }
           
          {
                  [color=Red]person = new Person (); //代码2[/color]          }
           
         [color=Red] public Person(){ //代码1
                  System.out.println(person);
          } [/color]}
你的程序首先执行代码1然后执行代码2,然后就一直循环执行代码1和代码2,是一个死循环,因为person类的构造方法执行的时候要先去执行代码块,然后执行构造函数,而代码块中有调用了构造方法,这样就死锁了,希望能帮你。
作者: 匿名    时间: 2011-9-21 09:31
public class Person {
         Person person;
        public static void main(String[] args) {
                Person a = new Person();
        }
        {
                System.out.println("aaaa");
                person = new Person();
        }

        public Person() {
                System.out.println(person);
        }
}
在程序块里打印一句话
输入:
aaaa
aaaa
aaaa
aaaa
aaaa
aaaa
aaaa
aaaaException in thread "main" java.lang.StackOverflowError
        at sun.nio.cs.ext.DoubleByteEncoder.encodeArrayLoop(DoubleByteEncoder.java:126)
        at sun.nio.cs.ext.DoubleByteEncoder.encodeLoop(DoubleByteEncoder.java:189)
        at java.nio.charset.CharsetEncoder.encode(CharsetEncoder.java:544)
        at sun.nio.cs.StreamEncoder.implWrite(StreamEncoder.java:252)
        at sun.nio.cs.StreamEncoder.write(StreamEncoder.java:106)
        at java.io.OutputStreamWriter.write(OutputStreamWriter.java:190)
        at java.io.BufferedWriter.flushBuffer(BufferedWriter.java:111)
        at java.io.PrintStream.newLine(PrintStream.java:495)
        at java.io.PrintStream.println(PrintStream.java:757)
        at Test.Person.<init>(Person.java:12)

说明先执行的是代码块的代码,再调用构造方法

假如这样改动代码
public class Person {
        static Person person = null;
        public static void main(String[] args) {
                Person a = new Person();
        }
        static{
                System.out.println("aaaa");
                 person = new Person();
        }
        public Person() {
                System.out.println(person);
        }
}
输出结果:
aaaa
null
Test.Person@de6ced
为什么会出先空值呢?
作者: 匿名    时间: 2011-9-21 10:09
是这样的

首先,你要明白的是,如果java.lang.StackOverflowError这个错误出现的话
它通常表示的是:你的内存已经被填满了,放不下更多的对象了
而内存为什么会被填满呢?那就是宋红旺童鞋的答案:
你的程序中产生了死循环,从而导致在内存中无限创建Person对象,最后使内存被填满并报错

===============================================

好,既然我们知道了报错的原因是程序中产生了死循环
那么我们就来看看为什么会产生死循环

首先,为了方便下一步的理解
我们可以根据楼上杨华童鞋测试的前半部分,得出两个结论:
1、程序首先会执行{}代码块的代码,然后才调用构造方法
2、每次创建一个Person对象的时候,{}代码块中的语句都要执行一次
[color=Red]*至于这两个结论是如何得出的,你就自己思考下吧呵呵[/color]

===============================================

好,了解上面两个结论以后,我们再来看看是哪里产生了死循环吧:

首先,根据上面的结论1:程序首先会执行{}代码块的代码,然后才调用构造方法
所以,当你第一次创建Person对象的时候
程序就会首先执行{}代码块中的代码
这时就会创建一个新的Person对象

然后,根据上面的结论2:每次创建一个Person对象的时候,{}代码块中的语句都要执行一次
所以,当程序在创建新的Person对象的时候,就又会先执行{}代码块中的代码
所以这时就又会创建一个新的Person对象

然后,根据上面的结论2:每次创建一个Person对象的时候,{}代码块中的语句都要执行一次
所以,当程序在创建新的Person对象的时候,就又会先执行{}代码块中的代码
所以这时就又会创建一个新的Person对象

……………………
这样很明显能看出来我的说法是循环了吧

===============================================

然后再回答一下杨华童鞋的问题吧~
其实,你的这个问题就是一个语句的执行顺序问题
与static代码块没有太大关系

当你在调用person = new Person();这行代码的时候
实际上这行代码的执行顺序是这样的:
1、首先调用new Person();构造方法,由于此时前面的"person ="还没有被执行,因此打印出来的是null
2、然后才会执行前面的"person =",将第1步中创建出的Person对象赋值给person
作者: 匿名    时间: 2011-9-21 11:08
欧拉
明白了
感谢各位大虾的热心解答




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2