java内部类的继承与覆写

本次内容见java编程思想384页Egg2()

外围类BigEgg2继承了外围类Egg2,且BigEgg2的内部类Yolk明确继承了Egg2的内部类Egg.Yolk之后,会出现什么情况?

package BigEgg;

class Egg2 {
      protected class Yolk {
        public Yolk() { System.out.println("Egg2.Yolk()"); }
        public void f() { System.out.println("Egg2.Yolk.f()");}
      }
      private Yolk y = new Yolk();
      {
          System.out.println("New Yolk2()");
      }
      public Egg2() { System.out.println("New Egg2()"); }
      //private Yolk y1 = new Yolk();
      protected void insertYolk(Yolk yy) { y = yy; }
      public void g() { y.f(); }
      
    }    

    public class BigEgg2 extends Egg2 {
      public class Yolk extends Egg2.Yolk { //通过继承明确的继承了Egg2.Yolk类,并覆盖了其中的方法
        public Yolk() { System.out.println("BigEgg2.Yolk()"); }
        public void f() { System.out.println("BigEgg2.Yolk.f()"); }
      } 
      //private Yolk y3 = new Yolk();
      public BigEgg2() { insertYolk(new Yolk()); }//向上转型成Egg2.Yolk类
      public static void main(String[] args) {
        Egg2 e2 = new BigEgg2();
        e2.g();
      }
    }

输出结果为

Egg2.Yolk()
New Yolk2()
New Egg2()
Egg2.Yolk()
BigEgg2.Yolk()
BigEgg2.Yolk.f()

现在来看一下这些结果的执行顺序:

首先调用new BigEgg2()的时候,首先会隐式调用父类Egg2的构造器,调用父类构造器之前,父类所有的数据域都会初始化为默认值,然后按顺序调用构造代码块,最后调用构造器。

这里面,父类的私有域y被显式初始化为new Yolk(),显式初始化语句是最开始被执行的,所以父类的内部类的构造器会第一个被执行,输出"Egg2.Yolk()"。执行完显式初始化语句后是构造代码块,输出"New Yolk2()",

最后才是父类的构造器,输出"New Egg2"。

接下来执行子类的构造器代码,此时已经创建了一个BigEgg2类型的对象,y还是从父类继承下来的,在执行insertYolk方法前应该指向的是父类中的Yolk类型。insertYolk方法是将类的数据域y指向传入它的参数,一个Yolk类型的对象,相当于给数据域赋值。

执行new Yolk(),因为BigEgg2中的内部类是Egg2中内部类Yolk的子类,所以先执行父类的构造器,再执行被覆写的子类的构造器,分别输出"Egg2.Yolk()"和"BigEgg2.Yolk()"。

posted @ 2019-11-04 15:31  fjlruo  阅读(389)  评论(0编辑  收藏  举报