CodeGym /课程 /JAVA 25 SELF /接口与抽象类的区别

接口与抽象类的区别

JAVA 25 SELF
第 20 级 , 课程 1
可用

1. 抽象类:回顾基础

在开始比较之前,先回顾一下什么是抽象类。

抽象类——是一种不能被直接实例化的类(不能写 new Animal()),但它既可以包含普通方法(有实现),也可以包含抽象方法(无实现)。抽象类常被用作其他类的基础,这些子类继承其行为并且/或者必须实现某些方法。

例如,在我们的应用中如果有不同的交通工具种类,可以定义一个抽象类 Transport

public abstract class Transport {
    private String model;

    public Transport(String model) {
        this.model = model;
    }

    public String getModel() {
        return model;
    }

    // 抽象方法——没有实现,只有声明
    public abstract void move();

    // 普通方法——有实现
    public void printInfo() {
        System.out.println("交通工具型号:" + model);
    }
}

抽象类的特点:

  • 可以包含字段(状态)。
  • 可以包含已实现的方法。
  • 可以包含抽象方法(子类必须实现)。
  • 不能直接创建实例。
  • 用于抽取通用的行为与状态。

2. 接口:回顾基础

接口是一组类必须实现的方法。接口不描述状态(不能有普通字段,只能有常量),并且在 Java 8 之前不包含方法实现。接口是一个纯契约:“如果你实现了我,你就必须会做这些事”。

接口示例:

public interface Movable {
    void move(int x, int y);
}

接口的特点:

  • 不包含状态(只有 public static final 常量)。
  • 在 Java 8 之前——只有抽象方法(自 Java 8 起出现了 defaultstatic 方法,稍后再谈)。
  • 方法默认总是 public abstract
  • 一个类可以实现多个接口。
  • 用于描述能力,即类“能做什么”。

3. 对比表:抽象类 vs 接口

是时候把这两种工具放在一起比较了!下面是一张直观的表格:

特性 抽象类 接口
语法
abstract class
interface
能创建实例吗? 不能 不能
能包含普通方法吗? 可以 Java 8 之前——不能,自 Java 8 起——只能有 default/static
能包含抽象方法吗? 可以 可以(Java 8 之前所有方法都是抽象的)
能包含字段(状态)吗? 可以(任意字段) public static final(常量)
能包含构造器吗? 可以 不能
继承 只能继承一个抽象/普通类 可以实现多个接口
方法修饰符 任意(publicprotectedprivate 方法默认是 public abstract。自 Java 9 起,可以添加 private 方法供接口内部使用
通过关键字
extends
implements
常见用途 共享实现与状态 描述能力与角色
JDK 中的示例
AbstractList, AbstractMap
Comparable, Runnable

4. 何时使用接口,何时使用抽象类?

在以下情况下使用接口:

  • 你只想描述类“能做什么”,而不关心它如何实现。
  • 你需要让一个类能够实现多个彼此独立的能力。
  • 示例:Comparable(可以比较)、Serializable(可以序列化)、Runnable(可以在线程中运行)。

在以下情况下使用抽象类:

  • 你想为所有子类提供统一的实现和状态。
  • 你需要所有子类都拥有特定的字段或已实现的方法。
  • 继承是严格的“单继承”:一个类只能继承一个(普通或抽象)类。

生活类比

  • 接口就像“驾驶证”:如果你拥有它,你就可以驾驶汽车,但没人规定你具体开什么车、怎么开。
  • 抽象类就像“通用的汽车蓝图”:所有车都有方向盘、踏板、发动机,但每个品牌会以各自的方式实现细节。

5. Java 标准库中的示例

接口:Comparable

public interface Comparable<T> {
    int compareTo(T o);
}

任何实现该接口的类都必须实现方法 compareTo。例如,StringIntegerLocalDate 等等。

抽象类:AbstractList

public abstract class AbstractList<E> implements List<E> {
    // 默认实现了部分 List 方法
    // 有些方法保持抽象
}

AbstractList已经实现了集合的一部分行为(例如添加/删除方法),但保留了一些方法为抽象,以便子类可以按照自己的方式实现。

6. 代码示例:实践中的对比

接口

创建一个接口及其实现类。

public interface Printable {
    void print();
}

public class Document implements Printable {
    @Override
    public void print() {
        System.out.println("正在打印文档…");
    }
}

抽象类

接下来是一个抽象类及其子类。

public abstract class Machine {
    public void turnOn() {
        System.out.println("机器已启动。");
    }

    public abstract void work();
}

public class Printer extends Machine {
    @Override
    public void work() {
        System.out.println("打印机正在打印…");
    }
}

类同时继承抽象类并实现接口

public class SmartPrinter extends Machine implements Printable {
    @Override
    public void work() {
        System.out.println("智能打印机正在工作…");
    }

    @Override
    public void print() {
        System.out.println("智能打印机正在打印…");
    }
}

7. 同时实现多个接口:为什么很强大

在 Java 中,一个类只能继承一个类(抽象或普通),但可以实现任意多个接口!这使你能够创建灵活、可扩展的架构。

public interface Scannable {
    void scan();
}

public class MultiFunctionPrinter extends Machine implements Printable, Scannable {
    @Override
    public void work() {
        System.out.println("多功能一体机正在工作…");
    }

    @Override
    public void print() {
        System.out.println("多功能一体机正在打印…");
    }

    @Override
    public void scan() {
        System.out.println("多功能一体机正在扫描…");
    }
}

什么时候该选哪一个?

  • 如果你在设计带有共享状态的基础功能(例如字段),请使用抽象类
  • 如果你想为对象添加“能力标签”(例如“能打印”“能比较”“能序列化”)——请使用接口
  • 如果不确定——从接口开始。在 Java 中这被视为良好实践:接口带来更高的灵活性与可扩展性。

8. 常见错误与坑点

错误 1:尝试继承多个类——Java 不允许!
一个类只能继承一个类,但可以实现多个接口。比如,class A extends B, C——这是错误的;而 class A extends B implements X, Y, Z——这是允许的。

错误 2:混淆了接口的字段与类的字段。
在接口中只能声明常量(public static final)。不能声明普通状态,例如 private int count;——编译器会立即阻止你。

错误 3:没有实现接口的全部方法。
如果类没有实现接口中的任意一个方法——它就必须被声明为 abstract,否则编译器会报错。

错误 4:试图创建接口或抽象类的实例.
这两种类型都是“半成品”。它们只能被扩展,不能直接实例化:

Printable p = new Printable(); // 错误!
Machine m = new Machine();     // 错误!

错误 5:认为接口可以有构造器。
接口不能有构造器,因为它们不描述对象的状态。只有类(普通类与抽象类)才可以。

评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION