继承是面向对象的三大特性之一
继承基本作用:代码复用;重要作用:有了继承才能有以后的“方法的覆盖”和“多态”
继承语法格式:
[修饰符列表] class 类名 extends 父类名{ 类体 }
Java语言当中的继承只支持单继承
术语:
B类继承A类,其中:
Java语言中子类继承父类:
Java语言中假设没有显示的继承任何类,默认继承JavaSE库提供的java.lang.Object类
public class ExtendsTest01 { public static void main(String[] args) { C c1 = new C(); c1.doSome(); // 这里调用的doSome方法是从B类中继承的 } } class A{ public void doSome() { System.out.println("do some !"); } } class B extends A{ } class C extends B{ }
【回顾】Java中的·方法重载:
方法重载称为Overload
什么时候能用
在同一个类当中,方法完成功能相似,建议方法同名
什么样条件构成方法重载
方法重载与什么无关
【正片】方法覆盖
方法覆盖【override官方】又被称作方法重写【overwrite】
什么时候使用方法覆盖
当父类中的方法已经无法满足当前子类的需求,子类有必要将父类中继承的方法进行重新编写,这个过程称为方法重写/方法覆盖
代码满足什么条件会触发方法覆盖?
方法重新建议复制过去改【防止写错】
注意:
// 创建动物类 public class Animal { public void move() { System.out.println("动物在移动"); } }
// 创建猫类 public class Cat extends Animal{ // 重新父类方法 public void move() { System.out.println("猫在走猫步"); } }
// 创建鸟类 public class Bird extends Animal{ // 重新父类方法 public void move() { System.out.println("鸟在飞"); } }
public class OverrideTest01 { public static void main(String[] args) { // 创建动物对象 Animal a = new Animal(); a.move(); // 创建猫对象 Cat c = new Cat(); c.move(); // 创建鸟对象 Bird b = new Bird(); b.move(); } }
Java中多态机制【基础规则】
多态作用:
降低程序的耦合度【解耦合】,提高程序的可拓展性【尽量使用】
面向对象三大特征:封装、继承、多态
关于多态中涉及的概念:
向上转型(upcasting)
子类型 --> 父类型
又被称为:自动类型转换
通过运行一定不会出问题
向下转型(downcasting)
父类型 --> 子类型
又被称为:强制类型转换【需要加强制类型转换符】
通过运行可能出问题【著名异常:java.lang.ClassCastException】
无论是向下转型(upcasting)还是向上转型(downcasting),两种类型之间必须要有继承关系。没有继承关系无法通过编译
当调用的方法是子类型特有,在父类型当中没有。必须进行向下转型(downcasting)
在向下转型(downcasting)中如何避免 ClassCastException
异常
使用 instanceof
运算符
(引用 instanceof 数据类型名)
计算结果为 Boolean【布尔类型】
Java规范中要求:在使用强制类型转换前,建议采用 instanceof
运算符判断,避免 ClassCastException
异常
Animal、Cat、Bird三个类之间的关系:
// 创建动物类 public class Animal { public void move() { System.out.println("动物在移动"); } }
// 创建猫类 public class Cat extends Animal{ // 重新父类方法 public void move() { System.out.println("猫在走猫步"); } // 不是从父类中继承的方法 // 这个方法是子类对象特有行为 public void catchMouse() { System.out.println("猫抓老鼠"); } }
// 创建鸟类 public class Bird extends Animal{ // 重新父类方法 public void move() { System.out.println("鸟在飞"); } // 子类对象特有行为 public void fly() { System.out.println("Bird fly !"); } }
public class Test { public static void main(String[] args) { // 以前编写的程序 // 创建动物对象 Animal a1 = new Animal(); a1.move(); // 创建猫对象 Cat c1 = new Cat(); c1.move(); c1.catchMouse(); // 创建鸟对象 Bird b1 = new Bird(); b1.move(); // 使用动态机制 System.out.println("-----以下使用动态机制----"); Animal a2 = new Cat(); // 想象 long num = 10; // Cat is a Animal // new Cat()创建的对象类型是Cat,Animal a2中 a2 引用的数据类型是Animal,可见它们进行类型转换 // 子类型转换父类型,称为向上转型(upcasting),或者自动类型转换 // Bird b2 = new Cat(); Bird与Cat无继承关系 // 编译器只会把a2类型视作Animal // 运行时是看底层的实际内容 a2.move(); // 猫在走猫步 // a2.catchMouse(); 报错 // 编译器检查为Animal类型,Animal中没有catchMouse()方法,导致静态绑定失败 // 需求:需要a2去执行catchMouse()方法 // 可以通过向下转型(downcasting),强制转换,同样需要两者有继承关系 Cat c2 = (Cat)a2; c2.catchMouse(); // 父类型引用指向子类型对象【多态】 // 以下程序编译无错语法允许,但运行阶段报错JVM堆内存实际存在的是Bird对象 // 类型之间不存在如何继承关系,会发生著名异常:java.lang.ClassCastException // 触发一般在向下转型(downcasting),一定注意 // Animal a3 = new Bird(); // Cat c3 = (Cat)a3; // c3.catchMouse(); 报错 著名异常:java.lang.ClassCastException // 避免ClassCastException Animal a3 = new Bird(); if(a3 instanceof Cat) { Cat c3 = (Cat)a3; c3.catchMouse(); }else if(a3 instanceof Bird){ Bird b3 = (Bird)a3; b3.fly(); } } }
a2.move();
一定调用Cat对象的move()方法【方法重写无关】,称为动态绑定,运行阶段绑定父类型引用指向子类型对象这种机制导致程序在编译阶段绑定和运行阶段绑定两种不同的形态,这种机制可以成为一种动态语法机制