继承&多态
一、 继承
- 若未显式指定,则所有的类都默认继承自
Object
类(Object 类是 Java 中唯一没有父类的类) - Java只支持单继承,不支持多重继承
- 被
final
修饰的类(比如String类)不能被继承
二、 方法重写
- 子类可以重写父类方法的前提:有权限访问父类方法
- 子类重写父类方法的格式:子类和父类中被重写的方法具有完全相同的方法名称以及参数列表
2.1 像重写的非重写
- 当子类与父类在同一包下时,子类无权访问父类中被
private
修饰的方法 - 当子类与父类不在同一包下时,子类无权访问父类中被
private
以及默认权限修饰符值修饰的方法
当出现以上两种情况时,即使子类的方法与父类中的方法有完全相同的方法名称以及参数列表,也不是方法的重写。(可以理解为重写是站在子类的角度看,若子类都无法访问父类,看不到父类有这个方法,又如何对这个方法进行重写)
2.2 真正的重写
当子类有权访问父类方法时,若子类和父类中的方法具有完全相同的方法名称以及参数列表,此时子类方法会重写父类方法。此时父类与子类中的方法必须符合以下要求,否则编译器会报错:
-
父类中的方法是非
final
的 -
子类重写方法的返回值类型不能大于父类被重写的方法的返回值类型(若返回值类型是基本数据类型和void,则必须相同)
-
子类重写方法使用的访问权限符不能小于父类被重写方法的访问权限
-
子类重写方法抛出的异常不能大于父类被重写方法的异常
-
子类与父类的方法必须同时是
static
或者非static
的(都是static时,并不是方法重写)当子类和父类中的方法都被声明为
static
时,这两个方法上也不是重写关系,而是成为了并列存在于各自类中的static
方法。
三、 多态
对象的多态性:父类引用指向子类对象
多态的前提:类之间有继承关系,且子类重写了父类方法
多态的语法形式:父类类型 变量名 = new 子类类型()
3.1 成员方法的多态性
引用变量有两种类型:
- 编译时类型:由声明该变量时使用的类型决定
- 运行时类型:由赋给该引用变量的实际对象类型决定
当编译时类型和运行时类型不一样时就出现了对象的多态性,此时当调用父类的方法且该方法被子类重写时,就会调用子类中被重写的方法(调用父类方法,实际运行子类中重写的方法)。
注:
当引用类型变量声明为父类的类型时,即使实际引用的是子类对象,该引用变量也不能再访问子类中特有的成员变量和方法,只能访问父类中的成员变量和方法。
3.2 成员变量的多态性
成员变量没有多态性,成员变量在编译时就已经确定其类型(而方法的调用是在运行时才解析的,这也被称为动态绑定),而不是在运行时。因此即使子类里定义了与父类完全相同的成员变量,该成员变量依然不可能覆盖父类中的成员变量。
四 、 向上转型
-
向上转型(自动完成)
当变量声明的类型大于变量实际引用的类型时,称之为向上转型。此时,编译时按照变量声明的类型处理,只能调用父类中的成员变量和方法;但运行时,仍然是变量所引用对象的类型,所以实际执行的是子类重写的方法,即多态性(但成员变量还是只能调用父类的成员变量)。
-
向下转型(强制转换)
当使用父类引用变量指向子类对象后,就不能调用子类拥有而父类没有的方法了。要想调用子类特有的方法,必须强制做类型转换,将父类引用变量的类型强制转换为子类的类型,即向下转型。此时,编译时将按照子类的类型处理,引用变量可以调用子类特有的方法了(成员变量也将调用子类的)。
五、 笔/面试题目
-
问:子类向上转型后调用的是父类还是子类中的方法?
答:若父类方法被重写了,调用的是子类中的方法;若父类方法没有被重写,调用的还是父类的方法。