高 基础
接口与抽象类区别#
一句话答案#
接口定义能力规范支持多实现,抽象类定义模板只能单继承;JDK8 后接口可有 default 方法,两者边界模糊。
核心要点
| 维度 | 接口 | 抽象类 |
|---|---|---|
| 继承 | 多实现 | 单继承 |
| 方法 | 抽象+default | 抽象+具体 |
| 变量 | 只能static final | 可以有实例变量 |
| 构造器 | 无 | 有 |
面试回答(2分钟版)
接口和抽象类在语法和设计语义上有明确区别。语法层面,接口支持多实现一个类可以实现多个接口,抽象类只能单继承;接口中的变量只能是 static final 的常量,抽象类可以有实例变量;接口没有构造器,抽象类有构造器可供子类调用。JDK 8 之后接口可以有 default 方法和 static 方法,这让接口也能提供默认实现,两者的边界变得模糊了一些。设计语义层面,接口定义的是能力规范,表示一个类能做什么,比如 Comparable 表示可比较、Serializable 表示可序列化;抽象类定义的是模板和继承体系,表示一个类是什么,比如 AbstractList 是列表的骨架实现。选择原则是:定义跨继承体系的能力契约用接口,定义同族类的公共模板和状态用抽象类。JDK 8 的 default 方法带来了菱形继承冲突问题,当一个类实现的两个接口有同签名 default 方法时必须手动重写解决冲突。函数式接口是只有一个抽象方法的接口,可以用 Lambda 表达式简洁实现。
追问与易错
追问方向:
- “JDK8 的 default 方法带来了什么问题?”→ 菱形继承冲突:当一个类实现的两个接口有同签名 default 方法时,编译器报错,必须手动重写该方法明确选择哪个实现
- “什么时候用接口什么时候用抽象类?”→ 定义跨继承体系的能力契约用接口(如 Comparable、Serializable);定义同族类的公共模板和共享状态用抽象类(如 AbstractList)
- “函数式接口是什么?”→ 只有一个抽象方法的接口(可用 @FunctionalInterface 注解标注),可以用 Lambda 表达式简洁实现,如 Runnable、Comparator、Function
易错点:
- ❌ “接口不能有实现”——JDK8+ 可以有 default/static 方法
- ❌ “抽象类必须有抽象方法”——不是必须的,可以全是具体方法