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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 朱东方 中级黑马   /  2012-7-12 23:40  /  1673 人查看  /  3 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

class Root   
{
static
{  
   System.out.println("1:Root静态构造代码块") ;
}   
{   
   System.out.println("2:Root普通构造代码块") ;
}
public Root() {
   System.out.println("3:Root构造函数") ;
}
}
class Mid extends Root   
{
static {     
   System.out.println("4:Mid静态构造代码块") ;
}
{  
   System.out.println("5:Mid普通构造代码块");
}
public Mid() {
   System.out.println("6:Mid无参构造函数") ;
}
public Mid(String msg) {  
   this ();
   System.out.println("7:Mid有参构造函数"+msg) ;
}
}
class Leaf extends Mid
{
static {   
   System.out.println("8eaf静态构造代码块") ;
}
{  
   System.out.println("9eaf普通构造代码块") ;
}
public Leaf() {   
   super("疯狂java讲义");  
   System.out.println("10eaf有参构造函数") ;  
}
}
public class demo {
public static void main(String[] args) {
   new Leaf() ;        
}
}


大家看看这个是怎么执行的。做上注释。明天我发答案

3 个回复

倒序浏览
哥们,前几天我也遇到这个问题,刚好有前辈回答了
下面我来总结他们的解答吧.
       
       
        要弄明白程序的执行顺序首先要明白 继承继承静态代码块构造代码块构造函数 的执行顺序,他们的顺序是:
父类静态代码块>>子类静态代码块>>父类构造代码块>>父类构造函数>> 子类构造代码块>>子类构造函数。
执行步骤(个人见解)
class Root    //第5步:找到Root,开始执行
{
static {  //第6步:由于有静态代码块,先执行静态代码块,进行初始化,打印1:Root静态构造代码块
  System.out.println("1:Root静态构造代码块") ;
}   
{   //第9步:执行父类的构造代码块,打印2:Root普通构造代码块
  System.out.println("2:Root普通构造代码块") ;
}
public Root() { //第10步:执行父类构造函数,打印3:Root构造函数
  System.out.println("3:Root构造函数") ;
}
}
class Mid extends Root    //第4步:找到Mid类,他又继承了Root,再去找Root类
{
static {     //第7步:Root初始化完成后寻找子类,也有静态代码块,先执行,并打印4:Mid静态构造代码块
  System.out.println("4:Mid静态构造代码块") ;
}
{   //第11步:执行性次构造代码块 打印5:Mid普通构造代码块
  System.out.println("5:Mid普通构造代码块");
}
public Mid() { //第12步:执行此构造函数,打印6:Mid无参构造函数
  System.out.println("6:Mid无参构造函数") ;
}
public Mid(String msg) {   //第13步:执行此构造函数打印7:Mid有参构造函数"+msg,msg由Leaf()调用super传入疯狂java讲义,所以打印Mid有参构造函数疯狂java讲义
  this ();
  System.out.println("7:Mid有参构造函数"+msg) ;
}
}
class Leaf extends Mid   
{
static {    //第8部:理由同第六步,打印8eaf静态构造代码块。静态代码块都完成了,再找父类的构造代码块
  System.out.println("8eaf静态构造代码块") ;
}
{   //第14部最后执行子类的构造代码块,打印9eaf普通构造代码块
  System.out.println("9eaf普通构造代码块") ;
}
public Leaf() {   //第2步,要new对象,找到Leaf的构造函数
  super("疯狂java讲义");  //第3步,调用父类,并且有参数 疯狂java讲义
  System.out.println("10eaf有参构造函数") ;  //第15步,打印10eaf有参构造函数
}
}
public class demo {
public static void main(String[] args) {
  new Leaf() ;        //第1步:找到main方法开始执行这一句,
}
}

再总结一下:
哥们你这代码太让人崩溃了……不过为了技术分,咱拼了!
关于对象初始化的问题,我也找了很多资料,写了很多测试代码,我就来说说吧
对象的初始化,有以下几项原则:
1.静态代码块,静态变量的显式初始化,会在类加载完成后进行
2.只是建立对象引用,类是不会加载的,只有要new 对象时,或者需要访问静态成员时,类才会加载
3.这条很重要,new出子类之前,会先去加载父类,也就是说先加载父类,再加载子类
4.构造代码块和成员变量的显式初始化会优先于构造函数执行,并且,构造代码块会在每一个构造函数之前执行
5.子类构造函数一定会调用父类的构造函数,如果程序员不调用,那么系统就默认调用父类的无参构造函数,当然程序员自己也可以手动调用
6.这条非常重要,构造函数并不是用来new对象的,而是对new出来的对象进行初始化的!!!

好,明确了这几点,我们再看代码,从main函数开始:
1.new Leaf();   使用Leaf()来创建Leaf对象,在这之前先加载父类 Mid,并使用Mid的构造代码块和 Mid(String msg) 对自己进行初始化,,
2.而Mid(String msg)又调用了Mid(),同理,在这之前又去加载Mid 的父类 Root了,并使用Root的构造代码块和 Root() 对自己进行初始化
3.此时Root加载完毕,接着执行他的静态代码区(这里我们不考虑Object,要不就太麻烦了)
4.Root 搞完了就该 Mid了,同样的,先执行静态代码区
5.Mid 加载完了 就该 Leaf了,同样执行 静态代码块,
6.所有的类都类加载完毕,静态代码区也都执行完了,那接下来就该是对象的初始化了
7.初始化的顺序就是:先使用父类的构造代码块和父类的构造函数初始化,在调用自己的构造代码块和构造函数
8.接下来就不多说了,先执行构造代码块,再执行构造函数,按照父子类构造函数的调用顺序逆向进行
按照上面所说,打印顺序为:
1:Root静态构造代码块
4:Mid静态构造代码块
8Leaf静态构造代码块
2:Root普通构造代码块
3:Root构造函数
5:Mid普通构造代码块
6:Mid无参构造函数
7:Mid有参构造函数疯狂java讲义
9Leaf普通构造代码块
10Leaf有参构造函数

再次感谢前辈对我的指导!

评分

参与人数 2技术分 +1 黑马币 +3 收起 理由
朱东方 + 3 很给力!
韦念欣 + 1 赞一个!

查看全部评分

回复 使用道具 举报
好厉害,哥们一来抢楼来吧。优活动
回复 使用道具 举报
本帖最后由 王红霞 于 2012-7-13 03:05 编辑

1-静态代码块优先于构造代码块执行  
2-执行子类时要先加载父类的构造函数,即加载leaf的时候 先加载root 再加载Mid


class Root   
{
    static//静态代码块 ;类一加载 static就加载了 所以这是第一步输出  1
   {  
        System.out.println("1:Root静态构造代码块") ;
   }   
   {   //构造代码块
        System.out.println("2:Root普通构造代码块") ;//然后即便是依次执行父类的构造函数和子类的构造函数 4
   }
    public Root()
    { //定义父类
       System.out.println("3:Root构造函数") ;//5
    }
}
class Mid extends Root   //子类
{
     static  
        {     //静态代码块  类一加载  static也即加载    所以这是第二部输出 2
        System.out.println("4:Mid静态构造代码块") ;
    }
    {  
       System.out.println("5:Mid普通构造代码块");//6

    }
    public Mid()
        {
        System.out.println("6:Mid无参构造函数") ;//7
    }
    public Mid(String msg)
        {  
        this ();
        System.out.println("7:Mid有参构造函数"+msg) ;//8
     }
}
class Leaf extends Mid
{
     static
         {   
         System.out.println("8eaf静态构造代码块") ;//类一加载 static就加载了  这是第三步输出   3
     }
     {  
         System.out.println("9eaf普通构造代码块") ;//  9
    }
     public Leaf()
        {   
     super("疯狂java讲义");  
     System.out.println("10eaf有参构造函数") ;  //10

     }
}
public class Demo
{
    public static void main(String[] args)
   {
       new Leaf() ;        
   }
}

打印结果如下图:

12.jpg (22.93 KB, 下载次数: 21)

12.jpg

评分

参与人数 1技术分 +1 收起 理由
刘笑 + 1 赞一个!

查看全部评分

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马