JAVA:继承和多态
第一章:继承——代码复用的艺术
1.1 继承的基本概念
定义:继承是面向对象三大特性之一,允许子类继承父类的属性和方法,并可以扩展或修改父类的功能。
核心术语:
- 父类(超类):被继承的类(如Animal)
- 子类(派生类):继承的类(如Lion)
- IS-A关系:子类是父类的一种特殊类型(狮子是动物)
1.2 继承的语法实现
基础语法:
class 子类 extends 父类 {// 新增属性和方法// 重写父类方法
}
完整示例:
// 父类:交通工具
class Vehicle {String brand;int maxSpeed;void start() {System.out.println(brand + "启动,最大速度" + maxSpeed + "km/h");}
}// 子类:汽车
class Car extends Vehicle {int seats; // 新增属性void openSunroof() { // 新增方法System.out.println("打开天窗");}
}public class Main {public static void main(String[] args) {Car myCar = new Car();myCar.brand = "奥迪";myCar.maxSpeed = 220;myCar.seats = 5;myCar.start(); // 调用继承方法myCar.openSunroof(); // 调用子类方法}
}
1.3 继承的内存原理
堆内存示意图:
+-------------------+
| Vehicle实例 |
| brand="奥迪" |
| maxSpeed=220 |
+-------------------+↑| 通过extends继承|
+-------------------+
| Car实例 |
| seats=5 |
+-------------------+
- 子类对象包含父类的所有字段
- 子类可以访问父类的非私有成员(需注意访问权限)
第二章:方法重写(Override)——赋予子类个性
2.1 方法重写的意义
问题引入:父类的通用方法无法满足子类特殊需求
class Bird {void fly() {System.out.println("鸟儿飞翔");}
}class Penguin extends Bird {// 企鹅不会飞,需要修改fly()行为
}
2.2 重写的语法规则
class Penguin extends Bird {@Overridevoid fly() {System.out.println("企鹅不会飞,只能摇摆行走");}
}
重写规则:
- 方法名和参数列表必须完全相同
- 返回类型可以是父类返回类型的子类(协变返回类型)
- 访问权限不能比父类更严格(public > protected > default > private)
- 不能重写
private
、final
、static
方法
2.3 @Override注解的重要性
- 编译器检查是否符合重写规则
- 提高代码可读性
- 避免意外重载(参数写错导致新方法)
错误示例:
class Parent {void show(int a) { ... }
}class Child extends Parent {@Overridevoid show(String a) { ... } // 编译错误:没有找到可重写的方法
}
第三章:super关键字——与父类沟通的桥梁
3.1 访问父类成员
场景:当子类与父类有同名成员时
class Animal {String name = "动物";
}class Cat extends Animal {String name = "猫咪";void printNames() {System.out.println(super.name); // 动物System.out.println(this.name); // 猫咪}
}
示例:
class Person {String name;public Person(String name) {this.name = name;}
}class Student extends Person {String major;public Student(String name, String major) {super(name); // 必须首先调用父类构造this.major = major;}
}
默认构造方法问题:
class A {public A(int x) { ... }
}class B extends A {// 错误:没有默认构造可用public B() { // 隐式super()会失败,因为A没有无参构造}
}
第四章:多态——同一接口,多种实现
4.1 多态的三要素
- 继承:存在继承关系的类体系
- 重写:子类重写父类方法
- 向上转型:父类引用指向子类对象
4.2 多态的基本使用
Animal animal = new Lion(); // 向上转型
animal.eat(); // 实际调用Lion的eat()
栈内存 堆内存
+----------+ +-----------------+
| animal | --> | Lion实例 |
+----------+ | Animal部分 || name, age || Lion特有属性 |+-----------------+
4.3 多态的优势
- 代码扩展性:新增子类不影响原有代码
- 统一接口:用父类类型管理不同子类对象
- 降低耦合:调用方无需知道具体子类类型
动物园管理示例:
Animal[] animals = new Animal[3];
animals[0] = new Lion();
animals[1] = new Penguin();
animals[2] = new Elephant();for (Animal a : animals) {a.eat(); // 每个动物执行自己的eat()
}
第五章:动态绑定——多态的实现原理
5.1 方法调用的两种方式
- 静态绑定:编译时确定方法(如private、final、static方法)
- 动态绑定:运行时根据对象类型确定方法
5.2 动态绑定示例
class Parent {void show() { System.out.println("Parent"); }
}class Child extends Parent {@Overridevoid show() { System.out.println("Child"); }
}public class Test {public static void main(String[] args) {Parent obj = new Child();obj.show(); // 输出Child(运行时决定)}
}
字节码分析:
aload_1 // 加载obj到操作数栈
invokevirtual #4 // 调用虚方法(动态查找实际方法)
第六章:抽象类与接口——多态的进阶形态
6.1 抽象类(Abstract Class)
使用场景:定义通用模板,强制子类实现特定方法
示例:
abstract class Shape {abstract double area(); // 抽象方法abstract double perimeter();void printInfo() { // 具体方法System.out.println("面积:" + area());}
}class Circle extends Shape {double radius;@Overridedouble area() { return Math.PI * radius * radius; }@Overridedouble perimeter() { return 2 * Math.PI * radius; }
}
6.2 接口(Interface)
核心特性:
- 完全抽象(Java 8前)
- 多继承实现
- 定义行为规范
示例:
interface Flyable {void fly();
}interface Swimmable {void swim();
}class Duck implements Flyable, Swimmable {@Overridepublic void fly() { System.out.println("鸭子飞翔"); }@Overridepublic void swim() { System.out.println("鸭子游泳"); }
}
6.3 接口的现代用法(Java 8+)
interface Logger {// 默认方法default void log(String message) {System.out.println("[INFO] " + message);}// 静态方法static void debug(String msg) {System.out.println("[DEBUG] " + msg);}
}
第七章:类型转换与instanceof——安全的多态操作
7.1 向下转型的风险
Animal animal = new Lion();
Lion lion = (Lion) animal; // 正确
Penguin penguin = (Penguin) animal; // 运行时错误:ClassCastException
7.2 instanceof操作符
if (animal instanceof Lion) {Lion lion = (Lion) animal;lion.run();
} else if (animal instanceof Penguin) {Penguin p = (Penguin) animal;p.swim();
}
7.3 模式匹配(Java 16+)
if (animal instanceof Lion lion) {lion.run(); // 直接使用lion变量
}
第八章:综合案例——电商支付系统设计
8.1 需求分析
- 支持多种支付方式(支付宝、微信、信用卡)
- 统一支付接口
- 方便扩展新支付方式
8.2 类图设计
<<interface>>
Payable
+ pay(double amount): boolean▲| 实现|
+-------+-------+-------+
| | | |
Alipay WeChatPay CreditCard
8.3 代码实现
interface Payable {boolean pay(double amount);
}class Alipay implements Payable {@Overridepublic boolean pay(double amount) {System.out.println("支付宝支付:" + amount);return true;}
}class PaymentProcessor {public void processOrder(Payable payment, double amount) {if (payment.pay(amount)) {System.out.println("支付成功");}}
}public class Main {public static void main(String[] args) {PaymentProcessor processor = new PaymentProcessor();processor.processOrder(new Alipay(), 100.0);processor.processOrder(new WeChatPay(), 200.0);}
}
第九章:常见问题与解决方案
9.1 构造方法继承问题
错误:子类忘记调用父类构造方法
class Parent {public Parent(int x) { ... }
}class Child extends Parent {// 编译错误:没有合适的父类构造
}
解决:显式调用父类构造
class Child extends Parent {public Child() {super(0); // 明确调用}
}
9.2 过度继承问题
反例:
Animal▲|
Mammal▲|
Dog▲|
GoldenRetriever
改进:优先使用组合
class Dog {private Breed breed; // 品种作为独立类
}
9.3 多态中的属性访问
class Parent { int x = 1; }
class Child extends Parent { int x = 2; }Parent obj = new Child();
System.out.println(obj.x); // 输出1(访问父类字段)
第十章:面向对象设计原则进阶
10.1 里氏替换原则(LSP)
定义:子类必须能够替换父类,且不影响程序正确性
违反示例:
class Rectangle {void setWidth(int w) { ... }void setHeight(int h) { ... }
}class Square extends Rectangle {// 改变父类方法行为void setWidth(int w) { this.width = w;this.height = w; }
}
10.2 依赖倒置原则(DIP)
定义:高层模块不应该依赖低层模块,二者都应依赖抽象
实践:
interface DataSource { ... }class Database implements DataSource { ... }
class FileSystem implements DataSource { ... }class ReportGenerator {private DataSource source;public ReportGenerator(DataSource src) {this.source = src;}
}
总结:
- 继承的语法与内存原理
- 方法重写的规则与实践
- 多态的实现机制与应用场景
- 抽象类与接口的异同
- 安全类型转换的方法
- 面向对象设计原则