目录
1. 定义
继承可以解决代码复用。当多个类中存在相同的属性(变量)和方法时,可以从这些类中抽象出相同的属性和方法,定义为父类,所有的子类不需要重新定义这些属性和方法,只需要通过 extends 来声明继承父类。
2. 继承示意图
3. 基本语法
class 子类名 extends 父类名{
//特有属性和方法
}
(1)子类会自动拥有父类定义的属性和方法。
(2)父类 又叫 基类,子类 又叫 派生类。
例:
4. 继承使用细节
(1)子类继承了父类的所有属性和方法,但是私有的属性和方法不能在子类直接访问,要通过父类提供的公共方法去访问。
(2)子类必须调用父类的构造器,完成父类的初始化。(在子类的构造器中,隐藏了 super(); 这句代码,这句代码会最先执行,完成对父类无参构造器的调用)
(3)当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器。如果父类没有提供无参构造器,则必须在子类的构造器中,用super去指定使用父类的哪个构造器完成对父类的初始化工作,否则,编译不会通过。
例:
(4)如果希望在子类构造器中,指定去调用父类的某个构造器,则使用super(参数列表); 显式的调用一下。
(5)super() 在使用时,必须放在构造器的第一行(super只能在构造器中使用)。
(6)super() 和 this() (this(参数列表); 按照前面this的学习,是对本类中构造器的调用)都必须放在构造器第一行,所以super()和this()不能在构造器中同时使用。如果定义了this(),默认隐藏定义的super也会取消。
(7)java所有类但是Object类的子类,Object是所有类的父类。
(8)父类构造器的调用不限于当前定义的直接父类,将一直向上追溯,直到Object类(顶级父类)。(因此,在创建子类对象时,会先从最顶级的父类构造器开始进行初始化,依次向子类调用)
(9)子类最多只能继承一个父类(指直接继承),所以Java中是单继承机制。
5. 继承的内存布局(重点)
(1)在main中创建子类对象son时
①先在方法区中加载类,按照继承关系,从Object依次向son进行加载。
②然后在堆中分配空间,依次从“GranPa”类开始分配属性空间,字符串就指向常量池中的地址。
③最后将整个空间的地址返回给主方法main中的son,进行引用。
(2)在main中,使用创建的子类对象调用属性或方法时(如 son.name; )
要按照查找关系来返回信息
①首先看子类是否有该属性,如果子类有这个属性,并且可以访问,则返回信息。不可以访问就报错。
②如果子类没有这个属性,就看父类有没有这个属性(如果父类有该属性,并且可以访问,就返回信息。不可以访问就报错)。
③如果父类没有就按照②的规则,继续找上级父类,直到0bject...。如果都没有找到,就报错。
④如果前面的父类中找到了对应的属性或方法,但是私有的,而在后面的父类中也有一个对应的属性或方法,是公有的。运行时,在前面的父类遇到私有不能访问时,就进行报错处理了,不会访问到后面的父类去。