Java 接口和抽象类对比|Java8 新特性,抛弃老旧八股,正确选型

基础不牢,地动山摇

大家好,这里是后端基础拾光集。

面试必考题:接口和抽象类有什么区别?我们一起来看看工作中具体怎么使用

一、生活化类比

把系统设计想成公司管理:

  • 接口 = 对外《岗位说明书》/能力认证 :只规定"这个岗位要做什么、必须会什么",不关心你是谁、你的内部属性是什么。不写"工号、薪资、审批权限、具体怎么干"。谁满足这份岗位要求,谁就能上岗;一个人还可以同时满足多份岗位说明书(一个类可以实现多个接口)。
  • 抽象类 = 内部《岗位族手册 + SOP + 员工档案模板》 :理解成半成品模板,它已经有一部分现成的属性、基础逻辑,不仅规定职责,还自带通用流程、共享字段、默认实现;子类像具体岗位,继承这个岗位族,补上差异部分。通常只能认一个主岗位族,你不能同时基于两份完全不同的半成品来打造同一个产品(一个类只能继承一个抽象类)。

一句话记忆:接口定能力规范;抽象类做半成品模板。

二、什么时候用接口?

当你在写"招聘要求"时,用接口:

  1. 只关心能力,不关心实现
    比如 Payable:只要"能支付"就行,微信、支付宝、银行卡各自怎么付,调用方不关心。
  2. 多个不相关类都要具备同一能力
    鸟、飞机、超人没有共同父类,但都可以实现 Flyable。
  3. 需要多角色、多能力组合
    一个类可以同时是 Readable、Writable、Closeable,像一个人可以同时有"程序员认证"和"Scrum Master认证"。
  4. 跨团队、跨模块定义契约
    UserService、OrderRepository、PaymentGateway 这类对外边界,优先用接口,方便替换实现、Mock 测试。
  5. 插件、策略、回调、依赖倒置
    调用方只依赖《岗位说明书》,不依赖具体员工。

典型:Runnable、Comparable、List、UserService。

三、什么时候用抽象类?

当你在写"岗位族标准手册 + 通用流程模板"时,用抽象类:

  1. 一组类本质上是同一类东西
    狗、猫、鸟都是 Animal,有共同字段如 name、age,也有共同方法如 eat()。
  2. 需要共享状态或初始化逻辑
    抽象类可以有字段、构造器。接口不能有实例状态。
  3. 需要默认实现,只留钩子给子类
    比如 AbstractList 实现了大量通用逻辑,子类只需实现 get()、size()。
  4. 固定流程,部分步骤可变
    模板方法模式:
    service() 固定"解析请求 -> 鉴权 -> 处理 -> 返回",其中 doGet()、doPost() 由子类实现。
    就像公司规定所有研发岗都走"接需求 -> 开发 -> 自测 -> 提测 -> 上线",但具体开发由前端、后端、算法各自完成。
  5. 需要 protected、构造器、非 public 扩展点
    这些接口做不到,抽象类可以。

典型:AbstractList、HttpServlet、InputStream、BaseService。

四、核心对比及选型(适配 Java8 + 新特性)

  1. 继承实现:抽象类用extends,接口用implements;一个类只能继承一个抽象类,但可以实现多个接口。
  2. 构造方法:抽象类可以有构造器,供子类初始化;接口不能有构造方法。
  3. 成员变量:抽象类可以有任意修饰符的成员变量;接口里的变量默认是public static final常量。
  4. 方法(重点!Java8 改动)
  • 抽象类:可以有抽象方法、普通实例方法、静态方法。
  • 接口:Java8 之前只能有抽象方法;Java8 新增default默认方法、static 静态方法;Java9 + 支持私有方法。
  1. 修饰符:抽象类方法可以用 public/protected/private;接口抽象方法默认 public。

怎么选?决策口诀

  • 只定职责、能力、契约:接口。
  • 要带共享状态、通用代码、SOP 模板:抽象类。
  • 多个不相关类只是"都能做某事":接口。
  • 多个类"本质同一族",还要复用代码:抽象类。
  • 需要多继承能力:接口。
  • 需要模板方法、固定流程:抽象类。
  • 既要对外契约,又要内部复用:接口 + 抽象类组合。

比如支付场景:

java 复制代码
interface Payable {
    void pay(BigDecimal amount);
}

abstract class AbstractPayment implements Payable {
    public final void pay(BigDecimal amount) {
        validate();
        doPay(amount);
        log();
    }

    protected abstract void doPay(BigDecimal amount);

    protected void validate() { /* 通用校验 */ }
    protected void log() { /* 通用日志 */ }
}

class WechatPay extends AbstractPayment {
    protected void doPay(BigDecimal amount) {
        // 微信支付具体实现
    }
}

这里:

  • Payable 是《岗位说明书》:必须能支付。
  • AbstractPayment 是《支付岗位族手册 + SOP》:校验、支付、日志流程固定,具体渠道动作由子类填。
  • WechatPay 是具体员工:继承岗位族,完成具体工作。

五、 最爱踩的坑

坑 1:认为接口只能写抽象方法

typescript 复制代码
// Java8+合法,接口可以有默认方法
public interface Logger {
    default void printLog(String msg){
        System.out.println("日志:" + msg);
    }
}

坑 2:分不清选型,有公共属性就无脑写接口

接口中定义的变量是常量,不能被子类修改。 如果子类需要拥有自己独有的成员属性,不要用接口,优先抽象类。

坑 3:为了复用代码强行使用抽象类

Java 是单继承,一旦继承抽象类,就不能再继承别的类。 如果只是定义能力规范,优先接口,不要占用唯一的继承名额。

✅选型建议

  • 只想定义「具备什么能力」,无公共属性:接口
  • 有大量共用字段、共用基础逻辑,需要半成品模板:抽象类

高频面试辨析

Q1:接口和抽象类都不能实例化? A:是的,两者都不能直接 new 创建对象。

Q2:接口的默认方法可以被重写吗? A:可以,子类实现接口后,可以重写 default 默认方法。

Q3:抽象类一定包含抽象方法吗? A:不一定。抽象类可以全部都是普通方法,只要加 abstract 修饰就是抽象类。

✅核心总结

  1. 接口:定义能力规范,多实现,变量默认常量,Java8 支持 default 默认方法。
  2. 抽象类:半成品模板,单继承,可以拥有实例变量、构造器。
  3. 选型原则:能力规范用接口;有共用属性、基础模板逻辑用抽象类。
  4. Java8 之后老八股失效,面试不要死记旧版本答案。

最终记住:

接口 = 岗位说明书 / 能力认证,解决"能做什么、谁都能挂这个角色"。
抽象类 = 岗位族手册 + SOP + 档案模板,解决"同一类东西怎么复用代码和流程"。
优先用接口定义契约;确实有共同状态和模板流程时,再用抽象类。


📝本文属于专栏「后端基础拾光集」系列。 这个专栏结合生活化案例、线上踩坑实例讲解 Java 基础。 同系列已经更新:ArrayList & LinkedList 源码、HashMap、红黑树、Java 泛型、异常体系、Integer 缓存池、equals & hashCode、static、final。 专栏持续更新 Java 后端基础、源码、面试踩坑干货,欢迎一起交流后端学习、面试踩坑经验。

相关推荐
量化分析码农1 小时前
【Python量化策略评估体系 #05】极端行情扛得住吗?2008/2015/2020 三场景压力测试
后端
caoerzhong1 小时前
JeeWMS 开源 WMS 部署避坑指南:Java 仓库管理系统的环境基线、四类根因与可复现交付
java·开发语言·开源
用户3721574261351 小时前
Java 合并 PDF 文件:完整合并、指定页面合并与流合并
java
IT_陈寒1 小时前
SpringBoot自动配置差点让我加班到凌晨
前端·人工智能·后端
用户8356290780511 小时前
使用 Python 对 Excel 工作表进行排序
后端·python
程序员cxuan1 小时前
腾讯又来一王炸,开源版 WorkBuddy 太夯了!
人工智能·后端·程序员
for_ever_love__2 小时前
MySQL 全文索引实战:FULLTEXT、ngram 中文分词与 MATCH AGAINST 到底该怎么用
java·python·mysql·全文检索·分词·索引·ngram
java资料站2 小时前
五、Spring AI Alibaba · Memory · Saver(短期会话)
java·spring·microsoft
用户8356290780512 小时前
使用 Python 合并 PowerPoint 演示文稿
后端·python