黑马程序员技术交流社区

标题: 静态代码块和继承问题 [打印本页]

作者: 黑马-许鹏    时间: 2013-5-20 22:44
标题: 静态代码块和继承问题
对于继承,多态先执行哪一段一直都搞不太清楚。为了弄清楚,今天写了一段代码测试了一下,不多说先上代码
  1. class Father{
  2.         private int x=3;
  3.         public int y=5;
  4.          Father(){
  5.                 System.out.println("Father  run");
  6.         }
  7.          static {
  8.                  System.out.println("Father staticCode run");
  9.          }
  10.          {
  11.                  System.out.println("Father structCode run");
  12.                  x++;
  13.                  y++;
  14.          }
  15.          public void show() {
  16.                   System.out.println("x="+x+",y="+y);
  17.          }
  18. }
  19. class Child extends Father {
  20.          private int x=13;
  21.          public int y=15;
  22.          Child(){
  23.                         System.out.println("child  run");
  24.          }
  25.          static {
  26.                  System.out.println("child staticCode run");
  27.          }
  28.          {
  29.                  System.out.println("child structCode run");
  30.                  x++;
  31.                  y++;

  32.          }
  33.          public void show() {
  34.                   System.out.println("x="+x+",y="+y);
  35.          }
  36. }


  37. public class Test {

  38.         public static void main(String[] args) {
  39.                 Father f=new Child();
  40.                 f.show();
  41.                 Child c=new Child();
  42.                 c.show();
  43.                
  44.         }

  45. }
复制代码
打印结果如下:
Father staticCode runchild staticCode run
Father structCode run
Father  run
child structCode run
child  run
x=14,y=16
Father structCode run
Father  run
child structCode run
child  run
x=14,y=16

根据打印结果分析:
        第一个创建对象是多态,应该是子类继承了父类的父类的静态代码块和构造代码块,当new一个子类对象时,静态代码块随着类的加载而加载,所以先执行两个静态代码块,再执行继承过来的原父类的构造代码块,但为什么接着是执行父类的构造方法,而再执行子类的构造代码块呢?{:soso_e132:}接着再执行子类的构造函数方法没有问题,最后f.show()执行的是子类的show方法这一点也比较疑惑{:soso_e132:}
       第二个创建的对象,child的引用指向child类的对象,因为静态代码块随着类的加载只执行一次,所以这次没有执行静态代码块,先执行的原父类中的构造代码块,这次依然是父类的构造函数先于子类的构造代码块执行,再次疑惑,{:soso_e132:}后面两项没什么疑惑的。
       分析的不对和疑惑的地方敬请各位批评和指点!!



作者: 刘勇强    时间: 2013-5-20 23:21
父类的构造函数在子类的构造代码块前执行的原因,和父类的构造函数在子类的构造函数前执行的原因是一样的吧,因为子类要继承父类,就需要先知道父类在初始化时都做了什么
但这里的具体语法原因我也不太明白,同求

至于f.show之所以执行子类的show方法,f引用指向的对象还是个子类对象,只不过被父类引用接受,执行时当然要执行子类自己的方法. 个人理解.
作者: 神之梦    时间: 2013-5-21 00:27
本帖最后由 神之梦 于 2013-5-21 01:02 编辑

个人理解,欢迎点评批判指正:
事实证明愚见一的解释不能解决楼主问题,求正解。。。。。
愚见一:先执行父类中的构造方法的原因:在new 子类对象时,跑到之类的构造方法去,因为每个子类中的第一行有个隐式的super();所以,就跑到父类中去执行父类的构造函数了。有时候第一行可能自己写上了个this();但不管怎样,子类的构造方法中,总有一个构造函数中的第一行有一个super语句,而因此也会先执行父类的构造函数。这是从代码上分析。从思路上同楼上观点一致。

愚见二:f.show();执行子类方法的原因:f虽然是父类型,但表示的是子类对象的引用。这点跟楼上观点一致,子类复写了父类中的show方法,所以执行的也将是子类的方法。
作者: 黑马-许鹏    时间: 2013-5-21 00:38
神之梦 发表于 2013-5-21 00:27
个人理解,欢迎点评批判指正:
愚见一:先执行父类中的构造方法的原因:在new 子类对象时,跑到之类的构造 ...

还是不懂。根据你的愚见一,先执行子类的构造代码块,再执行子类的构造方法,既然super()在子类的构造方法中的第一行,那也应该是先执行子类的构造代码块啊
作者: 神之梦    时间: 2013-5-21 01:01
本帖最后由 神之梦 于 2013-5-21 01:04 编辑
黑马-许鹏 发表于 2013-5-21 00:38
还是不懂。根据你的愚见一,先执行子类的构造代码块,再执行子类的构造方法,既然super()在子类的构造方 ...

仔细的分析了下,并翻阅了下以前的比较,确实是我记忆有误,我这种解释确实不靠谱。
因为构造代码块是优先于构造函数进行的,根据楼主的测试结果,可以看出对象一建立,就先跑到父类去执行构造代码块和构造函数,再来执行子类的构造代码块和构造函数。也许只能照沙发那哥们说的,子类继承父类,要先知道父类中初始化了些什么东西,再跑回来初始化自己的,可能这就是继承的执行顺序。应该也是可以从内存上来分析的,但菜鸟一枚,只是来学习的!

另外,楼主在主函数中,不许要去将父类型强转为子类型,因为意义不大,因为父类和子类中都只有一个方法,且子类复写了父类中的方法。只有在子类中也自己特有的方法要操作时,才需要强转,想必楼主应该也知会。。。




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