(转载)----继承成员内部类的步骤及代码分析

下面使用以下代码讲解成员内部类的继承

    package test7;  
       
    //第一步,引入内部类定义。无论该类是否如子类在同一个包下还是同一个文件下。  
    import test7.Person.Address;  
       
    public class ExtendsInnerClassTest {  
       public static void main(String[] args) {  
          Person p1 = new Person("forestqqqq",20);  
          new AddressDetail(p1,"TianJin","HeXi",1234).printAddress();  
       }  
       
    }  
       
    //外部类Person  
    class Person{  
       private String name;  
       private int age;  
       public Person(String name,int age){  
          this.name = name;  
          this.age = age;  
       }  
       //内部类Address  
       public class Address{  
          private String city;  
          private String street;  
          private int number;  
          public Address(String city,String street,int number) {  
            this.city = city;  
            this.street = street;  
            this.number = number;  
          }  
          public Address(int number){  
            this.city = "TianJin";  
            this.street = "HeXi";  
            this.number = number;  
          }  
          public void printAddress(){  
            System.out.println(name+"'s age is "+age+" and  Address is "+city+","+street+number);  
          }  
       }  
    }  
       
    //第二步,使用extends关键字,子类继承该内部类。  
    //内部类的子类AddressDetail  
    class AddressDetail extends Address{  
        
       //第三步,给子类的每一个构造方法传递一个参数,即外部类实例。  
       //(其实这一步是为第四步做准备的,只要第四步能够实现,这一步是可以省略的,  
       //也就是说,并不是每一个构造方法都需要传入外部类实例的,只要它能够实现第四步)  
       public AddressDetail(  
            Person p, //******这就是传入的的父类实例  
            String city,String street,int number){  
          //第四步,直接或间接(这里是直接)实例化父类内容  
          p.super(city,street,number);  
       }  
        
       //这个第三步省略了  
       public AddressDetail(){  
          //第四步,直接或间接(这里是间接)实例化父类内容  
          this(new Person("forestqqqq",20),"TianJin","HeXi",1234);  
       }  
    }  

第一 继承成员内部类的步骤(看代码和注释)

1import该类

2继承该类

3在每一个构造方法中添加一个参数,即外部类对象

4在构造方法的第一句,直接或间接的调用外部类对象的super方法,初始化父类内容

第二分析成员内部类的继承方式

 

想弄明白成员内部类的继承方式应该依次弄清楚以下这些知识点:

1内部类是Java语法规范,不是虚拟机规范。虚拟机不清楚Java语法中是否有内部类这种东西,也没精力去维护内部类与外部类之间的复杂的关系。虚拟机只是乐于加载一个又一个的class文件,而且它只知道每一个class文件就代表者一个单独的类就行了。

2内部类与外部类之间的复杂的关系,是在编译器编译java文件成为class文件时生成的。编译器将一文件中的每一个类(内部类或者外部类)分别编译成为不同的class文件。如上例中,编译之后生成4个class文件,即,ExtendsInnerClassTest.class、Person.class、Person$Address.class和AddressDetail.class。其中Person.class是外部类Person的class文件,Person$Address.class是内部类的class文件。

3编译器是通过改造内部类和外部类的构造方法、普通方法和属性定义来实现两个类之间的复杂联系的。

外部类Person反编译之后的结果:

class Person{  
   public Person(String name,int age){  
      //..  
   }  
   
   static String access$0(Person p){  
      return ..;  
   }  
    
   static int access$1(Person p){  
      return ..;  
   }  
   
   private String name;  
   private int age;  
} 

内部类Address反编译之后的结果:

class Person$Address{  
   public Person$Address(Person p,String city,String street,int number){  
      //..  
   }  
   public Person$Address(Person p,int number){  
      //..  
   }  
   
   public void printAddress(){  
      System.out.println(Person.access$0(this.this$0) + "'s age is " + Person.access$1(this.this$0) + " and  Address is " + this.city + "," + this.street + this.number);  
   }  
   
   private String city;  
   private String street;  
   private int number;  
   final Person this$0;  
} 

从代码上我们看到外部类Person中多了两个静态方法access$0和access$1,它们分别返回的是name和age,这两个方法是在编译时动态生成的,如果内部类中没有访问到name和age这两个外部类的属性,则这两个静态方法不会生成。正是因为内部类的printAddress方法中使用到了这两个属性,所以才就生成了这两个静态方法。

我们还看到内部类中多了一个外部类的引用属性:final Person this$0; 

这个属性保证了内部类与外部类的关联。

我们还看到,编译器改造了内部类的每一个构造方法,为每一个构造方法提供了一个外部类实例作为参数,实际上这个参数是用来初始化this$0这个属性的。这就保证了实例化内部类前必须实例化外部类对象。内部类就好像粘附在外部类实例上一样,外部类的实例总是先于内部类实例存在

4子类继承内部类也需要保证外部类实例先于内部类实例存在。所以子类实例的初始化顺序是,首先初始化外部类实例,然后初始化内部类内容,最后初始化子类独有的内容。因为经过编译器的改造后,内部类Address没有无参的构造方法,所以子类必须直接或者间接的调用父类的构造方法,但是父类每一个构造方法(经过改造后的)都要求有外部类的实例作为参数,所以,你必须给子类构造方法一个外部类实例。其实这是上面第三步和第四步的要求。

第四步的代码:

    p.super(city,street,number);  

是调用的内部类的构造方法,其实它在经过编译器改造之后是

super(p,city,street,number) 

目的就是实例化父类(内部类)的内容。

 

总结起来就一句话,父类内容先于子类内容存在,外部类内容先于内部类内容存在

 

这篇文章转自http://forestqqqq.iteye.com/

感谢博主大大的博文,每天进步一点点

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值