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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© java木 中级黑马   /  2014-5-18 05:11  /  1153 人查看  /  8 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

今天看毕老视的视频,在看对象初始化过程这节时。发现有个错误。
毕老师讲对象初始化时 先是默认初始化(成员变量先初始化),然后是构造代码块初始化。
那看下下面的代码。


public class car{
   car(String s) {
   System.out.println(s );
  }
  
  public static void main(String[] args) {
   dog1 d=new dog1();

  }
}
class dog1 {
  
  Cat o = new Cat("成员初始化");   A
  
  {
    System.out.println("构造代码块初始化");  B
  }

}
执行结果是
成员初始化执行
构造代码块初始化
从这结果看的确是默认初始化先执行,构造代码块后执行。
但是如果代码改成这样了。将AB两句代码的顺序掉换一下呢?执行的结果却是这样的。
构造代码块初始化
成员初始化执行
所以默认初始化和构造代码块初始化的执行顺序的优先级是一样的。JVM会以默认的先后执行顺序执行他们。

哈哈,毕老师也被我挑了个错,内心好澎湃啊!


8 个回复

倒序浏览
毕老师的没错:初始化先执行,代码块后执行.
  1. package com.itheima;

  2. public class test {
  3.        
  4.         public void funtion(){
  5.                
  6.                 System.out.println("代码块初始化");
  7.                
  8.         }
  9.        
  10.         public test(String s)
  11.         {
  12.                 System.out.print(s);
  13.         }
  14.        
  15.        
  16.         public static void main(String[] args) throws Exception{
  17.                 // TODO Auto-generated method stub
  18.                 test tt=new test("构造方法");
  19.                 tt.funtion();

  20.         }

  21. }
复制代码

//无论你怎样交换test()方法和function()方法,执行结果永远是:
C:\Documents and Settings\Administrator\桌面\2

评分

参与人数 1技术分 +1 收起 理由
SyouRai_Tsk + 1

查看全部评分

回复 使用道具 举报
基本就没错 嘿嘿每创建一个对象,构造代码块就会执行一次
回复 使用道具 举报
本帖最后由 Porsche911 于 2014-5-18 16:35 编辑

经过我的反复测试现总结如下:
先上代码
  1. public class Test
  2. {
  3.         public static void main(String[] args)
  4.         {
  5.                 Dog d = new Dog("构造函数初始化");
  6.         }
  7. }
  8. class Cat
  9. {
  10.         Cat(String str)
  11.         {
  12.                 System.out.println(str);
  13.         }
  14. }
  15. class Dog
  16. {
  17.         static Cat c1 = new Cat("静态成员初始化");

  18.         static
  19.         {
  20.                 System.out.println("静态代码块初始化");
  21.         }

  22.         Cat c2 = new Cat("成员初始化");

  23.         {
  24.                 System.out.println("构造代码块初始化");
  25.         }

  26.         Dog(String str)
  27.         {
  28.                 System.out.println(str);
  29.         }
  30. }
复制代码


当读到Dog d = new Dog("构造函数初始化");时,首先要加载Dog类,加载这个类的时候会为所有的静态成员变量初始化,同时执行静态代码块,这两者的顺序确实是按照代码的顺序执行。加载完毕后,创建了Dog类的实例对象,并为其所有非静态成员初始化,并执行构造代码块,而这两者的执行顺序也是按照代码的顺序执行,而最终执行构造函数。
大家可以把上述的代码换换位置试一下,就知道了。
回复 使用道具 举报 1 0
老师讲的没错,哥们儿,是你错了,首先,您提供的代码是没法运行的,Cat类是哪儿来的?其次,我将Cat类改成Car类在eclipse上运行后,和您说的结果是一样的,但是,您没有注意到,加载类是在构造代码块之前执行的,我的意思是说:因为你是在Car类里面new Dog1,然后在Dog1里又new Car,你将A写在B前面,new Dog1时需要加载类,此时Car类也被加载,打印出“成员初始化”,紧接着将地址赋给变量o,然后执行构造代码块,打印“构造代码块初始化”;同理,您将B放在A前面也是按照加载类,构造代码快,内存地址赋值的顺序进行,因为B在前,所以new Dog1时,先执行构造代码块,此时Car类已经加载,但是没有执行Car里面的构造函数,等构造代码块执行完毕后,在执行Car里得构造函数,在给内存赋值。
回复 使用道具 举报
小小6456 来自手机 初级黑马 2014-5-18 17:22:22
地板
学习了。。,。
回复 使用道具 举报
想了下,给你仔细回答下:
1.主函数进栈,加载car类
2.执行主函数到newDog时,加载dog类
3.由于代码A在B前面,而此时A代码所属类已经被加载,因此直接先运行A代码所属类的构造代码块,在运行A代码所属类的构造函数,接着往下运行B代码所属类的构造代码块,在运行B代码所属类的构造函数。
因此打印结果是:成员初始化执行 构造代码块初始化
4.交换代码A和B的位置,第3步骤稍有变化newDog时,加载Dog类,执行顺序改变B代码优先执行,即先运行B代码所属类的构造代码块,在运行B代码所属类的构造函数,接着遇到A代码直接先运行A代码所属类的构造代码块,在运行A代码所属类的构造函数。
因此打印结果是:构造代码块初始化 成员初始化执行
5.综上所述,代码块的优先级别肯定是高于构造函数和默认构造函数的,至于你所表达的观点,是由于类加载的顺序和该类创建对象的顺序所误导的。


不知道楼主搞懂没,认真的回答,版主给个技术分吧。
回复 使用道具 举报 1 0
大家在看下这个代码

package com.itheima.array;
public class Man {
public static void main(String[] args) {
  // TODO Auto-generated method stub
  woman a=new woman();
}
}
class woman{
{
  System.out.println("A构造代码块执行");A
}
B b=new B();B
}
class B{
{
  System.out.println("B构造代码块执行");
}
}
woman类的构造代码块与成员变量初始化,改变两者的前后顺序即(AB的顺序)打印结果同样会改变。难道还不能说明非静态成员初始化与构造代码块的执行顺序优先级是一样的吗?

回复 使用道具 举报
赵洋洋 发表于 2014-5-18 08:53
毕老师的没错:初始化先执行,代码块后执行.
//无论你怎样交换test()方法和function()方法,执行结果永远是:
...

我说的是非静态成员初始化和构造代码块执行顺序的优先级是一样的,不是代码块。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马