Java 继承
继承定义
如果有两个类相似,那么它们会有许多重复的代码,通过继承这一机制,可以实现代码的复用,使整个程序更加简洁,也便于维护。
- extends 关键字
语法class 子类 extends 父类
子类拥有父类除private以外的所有属性和方法。
子类可以拥有自己的属性和方法。
子类可以重写父类的方法。
Java 中的继承是单继承,一个类只有一个父类
在其他类中调用子类从父类继承的 protected 方法或成员变量时,该类和父类在同一个包中才可以访问。
若子类和父类不在同一个包中,则子类不能继承父类的友好变量和友好方法(所谓友好变量和友好方法,就是没有被 public 、private 、protected修饰的变量和方法)。
有时需要将某个类的的对象的引用转换成另一个类的对象的引用,转换的语法与数值表达式的类型转换类似。进行类型转换的唯一原因是:在暂时忽视对象的实际类型之后,使用对象的全部功能。举例来说,一个数组的元素类型既有超类对象也有子类对象,那么数组类型自然得定义成超类类型,而为了能够使用子类自己新增的方法和变量,那就需要进行类型转换。需要注意的是,只能在继承层次类进行类型转换,只能将超类转换成子类,建议转换前使用关键字 instanceof 进行检查。但是,这实际上并不是一种好的做法,大多数情况下也并不需要,真的需要的时候可能也是超类设计的不合理,应该尽量少用。
implements 关键字
使用 implements 关键字可以变相的使java具有多继承的特性,使用范围为类继承接口的情况,可以同时继承多个接口(接口跟接口之间采用逗号分隔)。语法
修饰符 interface A extends 接口1,接口2{ } 修饰符 class B implements 接口1,接口2{ }
更多参见:Java 多态:接口。
- 当一个类没有继承的两个关键字,则默认继承object(这个类在 java.lang 包中,所以不需要 import)祖先类。
也可以利用 Eclipse 帮我们自动建立继承关系。
下例创建一个 Dog 类继承自 Animal 类:
系统生成的代码:
package com.shiyanlou; public class Dog extends Animal { }
Dog 类里什么都没有写,其实它继承了父类 Animal,所以 Dog 类拥有 Animal 类的全部方法和属性(除了 private 方法和属性以外)。
重写
- 子类可以隐藏继承的成员变量,只要子类中定义个同名的成员变量即可。
- 子类可以重写继承自父类的方法,子类在调用方法时,优先调用子类的方法。
- 重写父类方法时,不可以降低方法访问权限。
- 重写的方法一定要与原父类的方法语法保持一致,比如返回值类型,参数类型及个数,和方法名都必须一致。
- 方法的重写(Overriding)和重载(Overloading)是java多态性的不同表现,重写是父类与子类之间多态性的一种表现,重载可以理解成多态的具体表现形式
相关知识
final 关键字
- final 修饰类,则该类不允许被继承,为最终类。
- final 修饰方法,则该方法不允许被重写。
- final 修饰属性,则该属性不会进行隐式的初始化(类的初始化属性必须有值)或在构造方法中赋值(但只能选其一),也就是说必须赋给初值。
- final 修饰变量,则该变量的值只能赋一次值,即常量。
super 关键字
- 访问父类的属性
super.属性名
。- 访问父类的方法
super.bark()
。- 子类构造方法需要调用父类的构造方法时,在子类的构造方法体里最前面的位置:
super()
。- 要想调用父类中被重写的方法,则必须使用关键字super。
- 注一:如果子类的构造方法中没有使用关键字 super ,那么默认有
super();
,即默认调用父类不带参数的构造方法。因此,若你在父类中实现了多个构造方法,那么 Java 不提供默认的不带参数的构造方法,则会在子类省略 super 时出错。综上,当自定义构造方法时,建议应包括一个不带参数的构造方法。- 注二:和关键字 this 作比较,this 有两个用途:一是引用隐式参数,二是调用该类其他的构造器。同样,super 关键字也有两个用途:一是调用超类的方法,二是调用超类的构造器。在调用构造器的时候,这两个关键字的使用方式很相似。调用构造器的语句只能作为另一个构造器的第一条语句出现。构造参数既可以传递给本类(this)的其他构造器,也可以传递给超类(super)的构造器。
初始化顺序
继承的初始化顺序是先初始化父类再初始化子类。也就是说你创建一个子类对象,它会先去创建一个父类对象,然后再创建子类对象。
注:父类的构造器(构造方法或构造函数)带有参数的,则必须在子类的构造器中显式地通过super关键字调用父类的构造器并配以适当的参数列表。如果父类有无参构造器,则在子类的构造器中用super调用父类构造器不是必须的,如果没有使用super关键字,系统会自动调用父类的无参构造器。
参考资料
- 菜鸟教程:Java 继承
- 实验楼:Java编程语言(新版)
- Java核心技术 卷Ⅰ基础知识 原书第8版
- Java2实用教程 (第三版)_ 耿祥义,张跃平
- 菜鸟教程:Java 重写(Override)与重载(Overload)