第一部分:接口 vs 抽象类总览

通过表格快速了解核心区别与联系

学习目标

掌握接口与抽象类的核心区别,能在实际开发中正确选择

对比维度 接口 (Interface) 抽象类 (Abstract Class)
关键字 interface abstract class
继承方式 implements extends
多继承 支持多实现 单继承
构造方法 ❌ 无构造方法 ✅ 可以有构造方法
默认实现 Java 8+ 支持 default 方法 可以有具体方法
成员变量 只能是 public static final 任意类型变量
访问修饰符 默认 public 支持任意修饰符
使用场景 定义能力/规范 代码复用与模板方法

第二部分:接口深入理解

从 Java 7 到 Java 17 接口的演进

1

经典接口定义

Java 7 及之前的接口只能包含常量和抽象方法:

public interface Drawable { // 默认就是 public static final int MAX_SIZE = 100; // 抽象方法,默认 public abstract void draw(); double calculateArea(); }
2

Java 8+ 接口增强

支持 default 和 static 方法:

public interface Resizable { void resize(double factor); // default 方法提供默认实现 default void reset() { System.out.println("Resetting to original size"); } // static 工具方法 static String getVersion() { return "1.0"; } }
3

接口实现示例

public class Circle implements Drawable, Resizable { private double radius; public Circle(double radius) { this.radius = radius; } @Override public void draw() { System.out.println("Drawing a circle"); } @Override public double calculateArea() { return Math.PI * radius * radius; } @Override public void resize(double factor) { radius *= factor; } }

第三部分:抽象类深入理解

抽象类的核心特性与模板方法模式

1

抽象类定义

public abstract class Shape { protected String color; protected boolean filled; // 构造方法 public Shape(String color, boolean filled) { this.color = color; this.filled = filled; } // 抽象方法 public abstract double getArea(); public abstract double getPerimeter(); // 具体方法 public String getColor() { return color; } // 模板方法模式 public final void displayInfo() { System.out.println("Color: " + color); System.out.println("Area: " + getArea()); System.out.println("Perimeter: " + getPerimeter()); } }
2

继承抽象类示例

public class Rectangle extends Shape { private double width; private double height; public Rectangle(double width, double height, String color, boolean filled) { super(color, filled); this.width = width; this.height = height; } @Override public double getArea() { return width * height; } @Override public double getPerimeter() { return 2 * (width + height); } }

第四部分:实战对比案例

通过同一个需求的不同实现方式来理解差异

1

需求:动物行为建模

需要表示不同动物的共性和特性行为

方案A:接口方式

// 定义能力接口 public interface Swimmable { void swim(); } public interface Flyable { void fly(); } public interface Animal { void eat(); void sleep(); } // 具体实现 public class Duck implements Animal, Swimmable, Flyable { @Override public void eat() { System.out.println("Duck eats"); } @Override public void sleep() { System.out.println("Duck sleeps"); } @Override public void swim() { System.out.println("Duck swims"); } @Override public void fly() { System.out.println("Duck flies"); } }

方案B:抽象类方式

public abstract class Animal { protected String name; public Animal(String name) { this.name = name; } // 抽象方法 public abstract void makeSound(); // 具体方法 public void eat() { System.out.println(name + " is eating"); } // 钩子方法 public boolean canFly() { return false; } } public class Bird extends Animal { public Bird(String name) { super(name); } @Override public void makeSound() { System.out.println(name + " chirps"); } @Override public boolean canFly() { return true; } }

第五部分:常见错误与最佳实践

总结开发中容易犯的错误和推荐做法

常见错误1:接口中的变量重新赋值

public interface Constants { int MAX_COUNT = 100; } // 错误:试图修改接口中的变量 Constants.MAX_COUNT = 200; // 编译错误!

接口中的变量默认是 public static final,不可修改

常见错误2:抽象类实例化

abstract class Shape { abstract double getArea(); } // 错误:试图实例化抽象类 Shape shape = new Shape(); // 编译错误!

抽象类不能直接实例化,必须通过子类实现

常见错误3:继承冲突

interface A { default void test() { System.out.println("A"); } } interface B { default void test() { System.out.println("B"); } } class C implements A, B { @Override public void test() { // 必须解决冲突 A.super.test(); // 或 B.super.test(); } }

最佳实践总结

  • 优先使用接口:当需要定义能力或规范时,使用接口更灵活
  • 使用抽象类进行代码复用:当有公共实现需要复用时,考虑抽象类
  • 组合优于继承:可以通过组合接口和抽象类来实现更灵活的设计
  • 接口命名:使用形容词或以 "-able" 结尾,如 Runnable, Comparable
  • 抽象类命名:使用名词,如 AbstractList, HttpServlet

第六部分:选择决策树

帮助你在实际开发中快速做出正确选择

选择接口的情况

  • 需要定义一组不相关的类共有的能力
  • 需要实现多继承
  • 需要定义回调或事件处理
  • 需要定义策略模式
  • 需要定义 API 契约

选择抽象类的情况

  • 需要在多个相关类间共享代码
  • 需要定义模板方法模式
  • 需要控制继承层次结构
  • 需要定义部分实现的骨架
  • 需要定义受保护的状态

实战练习

  1. 实现一个图形绘制系统,使用接口定义 Drawable,抽象类 Shape 提供基础实现
  2. 创建一个支付系统,使用接口定义 PaymentMethod,不同支付方式实现该接口
  3. 设计一个缓存系统,抽象类 Cache 提供基础功能,接口 Expirable 定义过期功能

第七部分:知识总结

一张思维导图总结所有核心知识点

接口特性

  • 多实现支持
  • Java 8+ 支持默认方法
  • 只能有静态常量
  • 隐式 public 抽象

抽象类特性

  • 单继承限制
  • 可以有构造方法
  • 支持实例变量
  • 支持各种访问修饰符

设计原则

  • 面向接口编程
  • 组合优于继承
  • 高内聚低耦合
  • 开闭原则

关键要点

记住这个口诀:"接口定义能力,抽象类复用代码;接口支持多实现,抽象类单继承;接口更灵活,抽象类更具体"