Java 完全指南 / 11 - OOP 进阶:继承、多态、抽象类、接口、内部类
11 - OOP 进阶:继承、多态、抽象类、接口、内部类
继承(Inheritance)
// 基类(父类)
public class Animal {
protected String name;
protected int age;
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
public void eat() {
System.out.println(name + " 正在吃东西");
}
public void sleep() {
System.out.println(name + " 正在睡觉");
}
@Override
public String toString() {
return name + ", " + age + "岁";
}
}
// 子类
public class Dog extends Animal {
private String breed; // 品种
public Dog(String name, int age, String breed) {
super(name, age); // 调用父类构造器(必须在第一行)
this.breed = breed;
}
// 子类特有方法
public void bark() {
System.out.println(name + " 汪汪叫!");
}
// 重写父类方法
@Override
public void eat() {
super.eat(); // 调用父类方法
System.out.println(" " + name + " 还摇尾巴");
}
@Override
public String toString() {
return super.toString() + ", 品种: " + breed;
}
}
public class Cat extends Animal {
private boolean isIndoor;
public Cat(String name, int age, boolean isIndoor) {
super(name, age);
this.isIndoor = isIndoor;
}
public void meow() {
System.out.println(name + " 喵喵叫!");
}
@Override
public void eat() {
System.out.println(name + " 优雅地吃猫粮");
}
}
多态(Polymorphism)
public class PolymorphismDemo {
// 方法参数使用父类类型 —— 接收任何子类
static void feedAnimal(Animal animal) {
System.out.print("喂食: ");
animal.eat(); // 运行时决定调用哪个子类的 eat()
}
public static void main(String[] args) {
// 向上转型(Upcasting)—— 自动
Animal dog = new Dog("旺财", 3, "金毛");
Animal cat = new Cat("咪咪", 2, true);
// 多态调用
dog.eat(); // 调用 Dog 的 eat()
cat.eat(); // 调用 Cat 的 eat()
// 同一方法,不同行为
feedAnimal(new Dog("小黑", 2, "拉布拉多"));
feedAnimal(new Cat("小白", 1, false));
// 向下转型(Downcasting)—— 需要强制转换
if (dog instanceof Dog d) { // JDK 16+ 模式匹配
d.bark();
}
// instanceof 安全检查
System.out.println("dog 是 Animal: " + (dog instanceof Animal)); // true
System.out.println("dog 是 Dog: " + (dog instanceof Dog)); // true
System.out.println("dog 是 Cat: " + (dog instanceof Cat)); // false
// 数组多态
Animal[] animals = {
new Dog("阿黄", 5, "中华田园犬"),
new Cat("橘猫", 3, true),
new Dog("哈士奇", 2, "哈士奇")
};
for (Animal a : animals) {
a.eat();
if (a instanceof Dog d) d.bark();
if (a instanceof Cat c) c.meow();
System.out.println("---");
}
}
}
抽象类(Abstract Class)
public abstract class Shape {
protected String color;
public Shape(String color) {
this.color = color;
}
// 抽象方法 —— 子类必须实现
public abstract double area();
public abstract double perimeter();
// 普通方法 —— 子类可以直接使用
public String getDescription() {
return String.format("%s %s: 面积=%.2f, 周长=%.2f",
color, getClass().getSimpleName(), area(), perimeter());
}
}
public class Circle extends Shape {
private double radius;
public Circle(String color, double radius) {
super(color);
this.radius = radius;
}
@Override
public double area() {
return Math.PI * radius * radius;
}
@Override
public double perimeter() {
return 2 * Math.PI * radius;
}
}
public class Rectangle extends Shape {
private double width, height;
public Rectangle(String color, double width, double height) {
super(color);
this.width = width;
this.height = height;
}
@Override
public double area() {
return width * height;
}
@Override
public double perimeter() {
return 2 * (width + height);
}
}
// 使用
public class ShapeDemo {
public static void main(String[] args) {
Shape[] shapes = {
new Circle("红色", 5),
new Rectangle("蓝色", 4, 6),
new Circle("绿色", 3)
};
double totalArea = 0;
for (Shape s : shapes) {
System.out.println(s.getDescription());
totalArea += s.area();
}
System.out.printf("总面积: %.2f%n", totalArea);
}
}
接口(Interface)
// 接口定义
public interface Drawable {
void draw(); // 抽象方法(默认 public abstract)
}
public interface Resizable {
void resize(double factor);
default double getScale() { // 默认方法(JDK 8+)
return 1.0;
}
static Resizable of(double scale) { // 静态方法
return factor -> scale * factor;
}
}
public interface Loggable {
String getLogMessage();
private void logToFile(String msg) { // 私有方法(JDK 9+)
System.out.println("[LOG] " + msg);
}
default void log() {
logToFile(getLogMessage());
}
}
// 多接口实现
public class GraphicShape implements Drawable, Resizable, Loggable {
private String name;
private double scale = 1.0;
public GraphicShape(String name) {
this.name = name;
}
@Override
public void draw() {
System.out.println("绘制 " + name + " (缩放: " + scale + ")");
}
@Override
public void resize(double factor) {
this.scale *= factor;
System.out.println(name + " 缩放至 " + scale);
}
@Override
public String getLogMessage() {
return name + " 已绘制,缩放: " + scale;
}
}
// 函数式接口(只有一个抽象方法)
@FunctionalInterface
public interface Validator<T> {
boolean validate(T value);
// 可以有多个默认方法
default Validator<T> and(Validator<T> other) {
return value -> this.validate(value) && other.validate(value);
}
}
接口 vs 抽象类
| 维度 | 接口 | 抽象类 |
|---|
| 关键字 | interface | abstract class |
| 多继承 | ✅ 实现多个接口 | ❌ 只能继承一个类 |
| 构造器 | ❌ 没有 | ✅ 有 |
| 字段 | 只有 public static final | 可以有各种字段 |
| 方法 | 抽象 + 默认 + 静态 + 私有 | 抽象 + 普通方法 |
| 设计理念 | “能做什么”(能力) | “是什么”(本质) |
Sealed 类(JDK 17+)
// 限制哪些类可以继承
public sealed interface Shape permits Circle, Rectangle, Triangle {}
public record Circle(double radius) implements Shape {}
public record Rectangle(double width, double height) implements Shape {}
public final class Triangle implements Shape {
private final double a, b, c;
public Triangle(double a, double b, double c) { this.a = a; this.b = b; this.c = c; }
}
// public class Pentagon implements Shape {} // ❌ 编译错误,未在 permits 列表中
// 配合 switch 模式匹配
public class ShapeCalculator {
static double area(Shape shape) {
return switch (shape) {
case Circle c -> Math.PI * c.radius() * c.radius();
case Rectangle r -> r.width() * r.height();
case Triangle t -> {
double s = (t.a() + t.b() + t.c()) / 2;
yield Math.sqrt(s * (s - t.a()) * (s - t.b()) * (s - t.c()));
}
};
// 不需要 default,编译器知道所有可能的子类型
}
}
内部类
public class OuterClass {
private String outerField = "外部字段";
// 1. 成员内部类
class MemberInner {
void show() {
System.out.println("成员内部类访问: " + outerField);
System.out.println("外部类引用: " + OuterClass.this);
}
}
// 2. 静态内部类(推荐)
static class StaticInner {
void show() {
System.out.println("静态内部类,不能访问外部实例成员");
}
}
// 3. 局部内部类
void method() {
class LocalInner {
void show() {
System.out.println("局部内部类访问: " + outerField);
}
}
new LocalInner().show();
}
// 4. 匿名内部类
Runnable task = new Runnable() {
@Override
public void run() {
System.out.println("匿名内部类实现 Runnable");
}
};
public static void main(String[] args) {
OuterClass outer = new OuterClass();
// 成员内部类需要外部类实例
MemberInner mi = outer.new MemberInner();
mi.show();
// 静态内部类
StaticInner si = new StaticInner();
si.show();
// 局部内部类
outer.method();
// 匿名内部类
outer.task.run();
}
}
内部类类型对比
| 类型 | 定义位置 | 访问外部类 | 使用场景 |
|---|
| 成员内部类 | 类成员 | 可访问所有成员 | 较少使用 |
| 静态内部类 | 类成员(static) | 只能访问静态成员 | 推荐,如 Map.Entry |
| 局部内部类 | 方法内 | 可访问 effectively final 变量 | 很少使用 |
| 匿名内部类 | 表达式中 | 同上 | 一次性使用 |
枚举实现接口
public enum Operation implements java.io.Serializable {
ADD("+") {
@Override
public double apply(double x, double y) { return x + y; }
},
SUBTRACT("-") {
@Override
public double apply(double x, double y) { return x - y; }
},
MULTIPLY("*") {
@Override
public double apply(double x, double y) { return x * y; }
},
DIVIDE("/") {
@Override
public double apply(double x, double y) { return x / y; }
};
private final String symbol;
Operation(String symbol) { this.symbol = symbol; }
public String getSymbol() { return symbol; }
public abstract double apply(double x, double y);
@Override
public String toString() {
return symbol;
}
}
// 使用
public class EnumInterfaceDemo {
public static void main(String[] args) {
for (Operation op : Operation.values()) {
System.out.printf("10 %s 3 = %.1f%n", op, op.apply(10, 3));
}
}
}
⚠️ 注意事项
- Java 只支持单继承 — 使用接口实现多重继承的效果。
- 优先使用组合而非继承 — 继承破坏封装,组合更灵活。
- 重写方法不能降低访问级别 —
public 不能重写为 private。 - 接口默认方法冲突 — 多接口有同名默认方法时,子类必须显式重写。
💡 技巧
- 静态工厂方法替代构造器 —
List.of()、Integer.valueOf()。 - 策略模式 — 使用接口 + Lambda 实现策略选择。
- 模板方法模式 — 抽象类定义骨架,子类实现具体步骤。
🏢 业务场景
- 策略模式:
Comparator 接口实现自定义排序。 - 适配器模式: 内部类实现接口适配。
- 模板方法: 抽象
AbstractController 定义请求处理流程。 - 状态模式: Sealed interface + record 表示有限状态。
📖 扩展阅读