[Java学习日记07】聊聊接口和抽象类

前言:关于"套娃"代码的终极拷问

坐标:图书馆 5 楼(靠空调位,今天风很大)

状态:刚改完一个被无限层级继承搞崩的 Bug。

碎碎念: 兄弟们,今天我彻底破防了。 本来想给我的项目加个新功能,结果发现原作者(也就是上个月的我)写了一堆深不见底的继承。我想改个方法,结果十几个子类全报错。 学长过来看了一眼,摇摇头说:"你这设计,属于是'过度继承',这种场景你应该用接口(Interface)而不是抽象类(Abstract Class)啊。"

回来后我反思了很久。原来这两者虽然都能用来"被继承",但底层逻辑完全不同。今天咱就来聊聊这两大"模板",看看它们到底怎么选!

🚀 目录

  1. [抽象类 (Abstract Class):未完成的"毛坯房"](#抽象类 (Abstract Class):未完成的“毛坯房”)

    • 1.1 什么是抽象类?

    • 1.2 它是为了"共性"而生

  2. [接口 (Interface):一份必须遵守的"协议"](#接口 (Interface):一份必须遵守的“协议”)

    • 2.1 什么是接口?

    • 2.2 它是为了"扩展"而生

  3. 核心对撞:一张表分胜负

  4. [哲学思考:is-a 与 has-a 的博弈](#哲学思考:is-a 与 has-a 的博弈)

    • 4.1 抽象类是"亲爹"

    • 4.2 接口是"考证"

  5. [JDK 8 之后的"叛变":接口居然能写实现了?](#JDK 8 之后的“叛变”:接口居然能写实现了?)

  6. 大厂面试:什么时候该用哪一个?

  7. 结语:代码的优雅在于克制

1. 抽象类 (Abstract Class):未完成的"毛坯房"

生活化场景: 学校要开发一个"学生管理系统"。所有学生(无论是 CS 的、经管的、还是艺术的)都有学号、名字,都要选课。 但不同专业的学生"写作业"的方式完全不一样。

这时候,我们可以搞一个 Student抽象类

1.1 什么是抽象类?

它是一个半成品

  • 它不能被 new 出来(你见过一个纯粹的、没有任何属性的"学生"对象吗?没有,他必须是某个具体的专业生)。

  • 它里面可以有已经写好的方法(大家共用的,比如 sleep()),也可以有没写完的方法(abstract 方法,比如 study())。

1.2 它是为了"共性"而生

抽象类强调的是**"身份(Identity)"**。它是子类的模板,子类是对它的细化。

复制代码
abstract class Student {
    String name;
    
    // 共性方法:大家都得睡觉
    void sleep() {
        System.out.println("在图书馆睡着了...");
    }
    
    // 抽象方法:具体怎么学,子类自己定
    abstract void study();
}

2. 接口 (Interface):一份必须遵守的"协议"

生活化场景: 不论你是学生、老师,还是校外的路人。只要你想进校门,你就得有"进校证(CanEnterSchool)"。 这个证件规定你必须具备"刷码(swipeCard)"和"出示健康信息(showInfo)"的功能。

2.1 什么是接口?

它是一份契约 或者规范

  • 接口只管"能干什么",不管"怎么干"。

  • 它里面全都是没有实现的"大饼"(除非是 JDK 8 以后的 default 方法)。

2.2 它是为了"扩展"而生

接口强调的是**"功能(Ability)"**。一个类可以实现多个接口。

  • 大学生比喻:我可以是一个"学生(抽象类继承)",同时我也可以拥有"英语四级(接口实现)"、"驾照(接口实现)"。

    interface DrivingLicense {
    void drive(); // 只要有驾照,你就得会开车
    }

3. 核心对撞:一张表分胜负

特征 抽象类 (Abstract Class) 接口 (Interface)
关键字 abstract class interface
关系 extends (继承) implements (实现)
数量 单继承(只能有一个亲爹) 多实现(可以考很多证)
变量 可以有普通变量 只能是常量 (public static final)
构造器 (供子类调用)
方法 可以有具体实现,也可以抽象 以前全是抽象,现在可以有 default

4. 哲学思考:is-a 与 has-a 的博弈

这是理解两者的灵魂所在。

4.1 抽象类是"is-a"

如果你觉得 A 是一个 B,那就用抽象类。

  • 是一个 动物。

  • CS学生 是一个 学生。

4.2 接口是"has-a"或"like-a"

如果你觉得 A 具有某种功能,那就用接口。

  • 具有 爬树的能力。

  • 这个类 具有 被序列化的能力(Serializable)。

5. JDK 8 之后的"叛变":接口居然能写实现了?

在很久以前,接口是纯粹的。但从 JDK 8 开始,为了支持 Lambda 表达式和方便版本升级,接口里可以写 default 方法和 static 方法了。

这就尴尬了:接口越来越像抽象类了? 其实不然。即便接口能写实现,它依然没有状态(成员变量) ,依然支持多实现。这些核心本质没变。

6. 大厂面试:什么时候该用哪一个?

面试官最喜欢问:"既然接口现在能写实现,那还要抽象类干嘛?"

你可以这样装杯(回怼)

  1. 如果你需要定义子类的共同属性(比如名字、年龄),抽象类是唯一的选择,因为接口不能存数据(只有常量)。

  2. 如果你需要约束不同类别的行为(比如灯能开关、电视也能开关),请用接口。

  3. 如果你想预留后路,建议用接口。因为 Java 是单继承,用了抽象类就把"亲爹位"占了,以后想改就难了。

7. 结语

写完这篇日记,我终于把之前的"套娃"代码重构完了。 我把那些乱七八糟的继承改成了接口组合,代码瞬间感觉清爽了许多。

作为大学生的我们:

  • 抽象类教我们要有深度(扎实的根基)。

  • 接口教我们要有广度(多样的技能)。

如果你也被"到底用哪个"纠结过,点个赞支持一下!下期咱们聊聊Java的异常体系

相关推荐
weixin_440784114 小时前
【HandlerThread实现原理】
android·java·开发语言
天空'之城4 小时前
C 语言工业级通用组件手写 24:互补滤波
c语言·开发语言·互补滤波·嵌入式算法·工业级组件
leoZ2314 小时前
本地跑大模型实战(七):llama.cpp 性能调优,让推理更快更省
java·人工智能·spring·生成对抗网络·语言模型·自然语言处理·llama
XR1234567884 小时前
工厂车间无线网络方案对比:AGV漫游哪家强?
开发语言·php
傻啦嘿哟5 小时前
某短视频平台视频爬虫实战:抓取推荐流视频信息,绕过反爬的3种技巧
开发语言·爬虫·python
現実君5 小时前
【硬件进阶】AD22上位替换JLEDA教程
开发语言·php
mubei-1235 小时前
SpringDAO的用法
java·开发语言·数据库
happymagic5 小时前
java spring boot做的jar包程序,如何实现自动运行启动
java·运维·服务器·spring boot·jar
格林威8 小时前
多相机微秒级对齐:硬件触发 vs PTP(IEEE 1588)方案实战对比
开发语言·人工智能·数码相机·机器学习·计算机视觉·视觉检测·机器视觉
都叫我大帅哥8 小时前
给 Java 程序员的 CSRF 攻击详解:从原理到防御实战
java