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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 高鑫 中级黑马   /  2012-5-5 19:17  /  1663 人查看  /  2 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

  1. class Demo
  2. {
  3.         static Demo d=new Demo();       //《1》
  4.         Demo()
  5.         {}
  6. }
  7. class Test
  8. {
  9.         public static void main(String[]args)
  10.         {
  11.                 Demo a=new Demo();        //《2》
  12.         }
  13. }
  14.        

  15. //-------------------------------程序二----------------------------------------
  16.        
  17. class Demo
  18. {
  19.         Demo d=new Demo();                        //《3》
  20.         Demo()
  21.         {
  22.         }
  23. }
  24. class Test
  25. { public static void main(String[] args)
  26.         {
  27.                 Demo a=new Demo();                //《4》
  28.         }
  29. }
复制代码
程序一中,运行class Test我认为是这样执行的:
1,读到《2》时,先把Demo类加载进内存
2,这时运行《1》,创建一个Demo类的对象
3,然后创建的对象的地址赋值给d,d存放在方法区,这时内存加载完成
4,程序又回到《2》,创建第二个Demo类的对象
5,把第二个Demo对象的地址赋值给a,a在栈内存中
请问以上步骤我理解的是否正确,是否有少了什么步骤?
程序二中,
1,运行到《4》时加载Demo类进内存
2,当运行到《3》时,创建Demo类的对象,因为d不是静态的,放在堆内存,所以这里貌似陷入了一种创建对象和加载类的循环,但我搞不明白这个循环的步骤是怎么样的。谁能详细告知。还有这个对象(《3》代码建立的对象)到底建立起来了没有??
为什么程序2编译可以通过呢?

2 个回复

倒序浏览
第一张的图 红色的是步骤
第二个程序堆内存溺出了,不停的创建Demo对象
回复 使用道具 举报
关于在JAVA中对象的实例化步骤。
这个在11 行实例化的时候。会先给静态变量分配内存空间并初始化,即使静态变量写在最后
也会先被执行。然后执行静态代码块。
  1. static{
  2. System.out.println("test");
  3. }
复制代码
这句会在静态变量初始化完了之后去执行。
当然而你这里没有静态代码块。只有一个静态变量:
  1. static Demo d=new Demo();
复制代码
这句就会在最先执行。这时候d就会被存放在方法区。
然后再在内存中为Demo分配内存空间,并做默认初始化。也就是所有的变量都初始化为默认变量。
完了之后,再做显示赋值。然后执行非静态方法块。最后执行默认构造方法。如:
在你的11 行下面加一句:
  1. {
  2.         System.out.println("test....");
  3.       }
复制代码
那么它就会在你的构造函数先被执行。
然后再去执行所谓的构造方法。
当然你的第二个方法。可以编译过!但是运行会报错。
我想是因为编译器只是去严格的去检查语法。关于这个运行时的错误是不会检查到的。
就像你去写了个死循环。那么编译器是不会给你检查出来的。这些个都是运行时错误。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马