【Java零基础·第8章】面向对象(四):继承、接口与多态深度解析
Java面向对象进阶:继承、接口与多态深度解析
在Java面向对象编程中,继承、接口和多态是三大核心特性,它们共同支撑起Java代码的复用性、扩展性和灵活性。本文将从基础概念出发,结合实例详细讲解这些特性,帮助你深入理解并灵活运用。
一、继承:代码复用的基石
1.1 继承的核心意义
继承是类与类之间建立"is-a"关系的机制,主要有三大作用:
- 代码复用:子类可以直接使用父类的非私有成员(变量和方法)
- 功能扩展:子类可以在父类基础上添加新功能
- 关系建模:清晰表达事物间的层次关系(如"狗是动物")
1.2 继承的关键特点
-
单继承限制:Java类只能有一个直接父类
// 正确:单继承 class Animal {} class Dog extends Animal {}// 错误:多继承不允许 class Flyable {} class Bird extends Animal, Flyable {} // 编译错误
-
多层继承支持:可以形成继承链
class Animal {} class Mammal extends Animal {} class Dog extends Mammal {} // Dog间接继承Animal
-
构造器不继承:子类必须调用父类构造器
class Parent {public Parent(String name) {} }class Child extends Parent {public Child() {super("默认名称"); // 必须显式调用父类有参构造} }
-
成员继承规则:
- 父类非私有成员会被继承
- 私有成员无法直接访问,但可通过父类提供的公共方法访问
- 子类可重写父类方法(方法签名相同,访问权限不降低)
1.3 方法重写实战
方法重写是子类对父类方法的重新实现,体现了多态性:
// 父类
class Animal {public void makeSound() {System.out.println("动物发出声音");}
}// 子类重写方法
class Cat extends Animal {@Override // 注解检查重写的正确性public void makeSound() {System.out.println("猫喵喵叫");}// 扩展新方法public void climbTree() {System.out.println("猫会爬树");}
}public class TestInheritance {public static void main(String[] args) {Animal animal = new Cat();animal.makeSound(); // 输出"猫喵喵叫"(体现多态)// animal.climbTree(); // 错误:父类引用不能调用子类特有方法}
}
二、抽象类:不完全的类定义
2.1 抽象类的特性
抽象类是包含抽象方法的类,具有以下特点:
- 不能直接实例化对象
- 可以包含普通方法和抽象方法
- 必须被继承才能使用
- 有构造器(供子类调用)
// 抽象类定义
abstract class Shape {// 抽象方法(没有方法体)public abstract double calculateArea();// 普通方法public void printInfo() {System.out.println("这是一个图形");}
}
2.2 抽象类的继承要求
子类继承抽象类必须遵循:
- 若子类非抽象类,必须重写所有抽象方法
- 若子类是抽象类,可选择性重写抽象方法
// 非抽象子类必须重写所有抽象方法
class Circle extends Shape {private double radius;public Circle(double radius) {this.radius = radius;}@Overridepublic double calculateArea() {return Math.PI * radius * radius;}
}// 抽象子类可不用重写所有抽象方法
abstract class AbstractRectangle extends Shape {// 没有重写calculateArea(),仍然是抽象类
}
三、接口:行为规范的定义
3.1 接口的基本概念
接口是方法规范的集合,更彻底的抽象,主要用于定义类应该实现的行为。
// 接口声明
public interface Flyable {// 公共静态常量(默认public static final)int MAX_HEIGHT = 10000;// 抽象方法(默认public abstract)void fly();// JDK8+默认方法default void land() {System.out.println("安全着陆");}// JDK8+静态方法static void showMaxHeight() {System.out.println("最大飞行高度:" + MAX_HEIGHT);}
}
3.2 接口的实现与继承
类实现接口使用implements
关键字,接口间可多继承:
// 接口继承
interface AnimalBehavior {void eat();
}interface BirdBehavior extends Flyable, AnimalBehavior {void buildNest();
}// 类实现接口
class Sparrow implements BirdBehavior {@Overridepublic void fly() {System.out.println("麻雀低空飞行");}@Overridepublic void eat() {System.out.println("麻雀吃虫子");}@Overridepublic void buildNest() {System.out.println("麻雀筑巢");}
}
3.3 接口成员冲突解决
- 父类与接口变量冲突
class Vehicle {int speed = 60;
}interface FastMove {int speed = 120;
}class Car extends Vehicle implements FastMove {public void showSpeed() {System.out.println("父类速度:" + super.speed); // 60System.out.println("接口速度:" + FastMove.speed); // 120}
}
- 父类方法与接口默认方法冲突
遵循"类优先"原则,优先使用父类方法:
class Parent {public void swim() {System.out.println("父类游泳方式");}
}interface Swimmable {default void swim() {System.out.println("接口默认游泳方式");}
}class Child extends Parent implements Swimmable {// 不重写swim(),默认使用Parent的swim()
}
- 多接口默认方法冲突
必须显式重写并指定使用哪个接口的方法:
interface A {default void method() {System.out.println("A的方法");}
}interface B {default void method() {System.out.println("B的方法");}
}class C implements A, B {@Overridepublic void method() {A.super.method(); // 使用A的默认方法B.super.method(); // 使用B的默认方法System.out.println("C自己的实现");}
}
四、经典接口:比较器接口
4.1 Comparable接口(自然排序)
实现该接口可以定义对象的自然排序方式:
public class Student implements Comparable<Student> {private String name;private int score;public Student(String name, int score) {this.name = name;this.score = score;}// 按分数升序排序@Overridepublic int compareTo(Student other) {// this > other:返回正整数// this < other:返回负整数// 相等:返回0return this.score - other.score;}public static void main(String[] args) {Student s1 = new Student("张三", 85);Student s2 = new Student("李四", 92);if (s1.compareTo(s2) > 0) {System.out.println(s1.name + "成绩更高");} else {System.out.println(s2.name + "成绩更高");}}
}
4.2 排序应用
利用Comparable实现数组排序:
import java.util.Arrays;public class SortDemo {public static void main(String[] args) {Student[] students = {new Student("张三", 85),new Student("李四", 92),new Student("王五", 78)};Arrays.sort(students); // 依赖Comparable接口for (Student s : students) {System.out.println(s.name + ":" + s.score);}}
}
五、多态:面向对象的精髓
5.1 多态的两种形式
- 编译时多态:方法重载
class Calculator {// 重载:相同方法名,不同参数列表public int add(int a, int b) {return a + b;}public double add(double a, double b) {return a + b;}public int add(int a, int b, int c) {return a + b + c;}
}
- 运行时多态:方法重写 + 多态引用
class Animal {public void move() {System.out.println("动物移动");}
}class Fish extends Animal {@Overridepublic void move() {System.out.println("鱼游");}
}class Bird extends Animal {@Overridepublic void move() {System.out.println("鸟飞");}
}public class PolymorphismDemo {public static void main(String[] args) {Animal animal;animal = new Fish();animal.move(); // 输出"鱼游"animal = new Bird();animal.move(); // 输出"鸟飞"}
}
5.2 多态的核心原则
“编译时看左边,运行时看右边”:
- 编译时检查引用类型(左边)是否有该方法
- 运行时执行实际对象类型(右边)的方法实现
5.3 多态的应用场景
- 多态数组:统一管理不同子类对象
public class ShapeArrayDemo {public static void main(String[] args) {Shape[] shapes = {new Circle(5),new Rectangle(4, 6),new Triangle(3, 4, 5)};for (Shape s : shapes) {System.out.println("面积:" + s.calculateArea());}}
}
- 多态参数:简化方法定义
class Printer {// 一个方法处理所有Shape子类public void printArea(Shape shape) {System.out.println("面积:" + shape.calculateArea());}
}// 使用
Printer printer = new Printer();
printer.printArea(new Circle(5));
printer.printArea(new Rectangle(4, 6));
- 多态返回值:灵活返回不同子类对象
class ShapeFactory {public static Shape createShape(String type) {switch (type) {case "circle": return new Circle(5);case "rectangle": return new Rectangle(4, 6);default: throw new IllegalArgumentException("未知形状");}}
}
5.4 类型转换与instanceof
- 向上转型:子类对象→父类引用(自动转换)
Bird bird = new Bird();
Animal animal = bird; // 向上转型
- 向下转型:父类引用→子类对象(强制转换)
Animal animal = new Bird();
// 必须先检查类型,否则可能抛ClassCastException
if (animal instanceof Bird) {Bird bird = (Bird) animal; // 向下转型bird.sing(); // 调用子类特有方法
}
- instanceof关键字:检查对象实际类型
Animal animal = new Bird();
System.out.println(animal instanceof Animal); // true
System.out.println(animal instanceof Bird); // true
System.out.println(animal instanceof Fish); // false
六、关键字总结
6.1 this关键字
代表当前对象,用于:
- 区分成员变量和局部变量
- 调用本类其他构造器
- 调用本类其他方法
class Person {private String name;public Person() {this("默认名称"); // 调用本类有参构造}public Person(String name) {this.name = name; // 区分成员变量和参数}public void printName() {System.out.println(this.name); // 调用本类成员变量}
}
6.2 super关键字
代表父类对象,用于:
- 访问父类成员变量
- 调用父类方法
- 调用父类构造器
class Parent {protected String name = "父类名称";public void print() {System.out.println("父类print方法");}
}class Child extends Parent {private String name = "子类名称";public Child() {super(); // 调用父类构造器}public void showNames() {System.out.println("子类名称:" + this.name);System.out.println("父类名称:" + super.name);}public void testPrint() {super.print(); // 调用父类print方法this.print(); // 调用子类print方法}@Overridepublic void print() {System.out.println("子类print方法");}
}
总结
继承、接口和多态是Java面向对象编程的三大支柱:
- 继承实现了代码复用和层次关系
- 接口定义了行为规范,支持多实现
- 多态实现了动态绑定,提高了代码灵活性
掌握这些概念并灵活运用,能够帮助你编写更优雅、更可扩展的Java代码。在实际开发中,合理设计类层次结构,正确使用接口定义规范,充分利用多态特性,是写出高质量面向对象代码的关键。