一、抽象类和接口的主要区别表格
| 特性 | 抽象类 | 接口 |
|---|---|---|
| 声明关键字 | abstract | interface |
| 声明访问修饰符 | public、protected、default(不能用private) | public、default |
| 继承关键字 | extends | implements |
| 变量 | 跟普通类一样,可以包含实例变量、静态变量等 | 只能包含静态最终变量 (public static final) |
| 构造函数 | 可以有构造函数 | 不能有构造函数 |
| 方法 | 可以有抽象方法、具体方法 | 只能包含抽象方法 (Java8开始可以有静态方法、 默认方法,Java9开始可以有默认方法) |
| 定义抽象方法 | 需要显式标注abstract | 默认 public abstract(不用显示标注) |
| 继承/实现 | 1.一个类只能继承一个抽象类 2.子类可以直接复用抽象类中的普通方法和普通字段 | 1.一个类可以实现多个接口 2.而接口中不能包含普通方法, 子类必须重写所有的抽象方法 |
| 使用场景 | 用于存在is-a关系、具有共同特征的类,并且希望共享代码实现 | 用于定义类必须实现的行为, 无论这些类是否有关联 |
二、详细解释:抽象类和接口代码细节上的区别
讲解逻辑:按代码的结构展开
声明{
成员变量
方法
}
1.声明
A:关键字
抽象类用abstract修饰
接口用interface修饰
在idea中的图标:
(抽象类的图标类似一颗棒球)
(接口图标)
B:声明修饰符
- 抽象类修饰符:
| 抽象类可以使用的访问修饰符 | 特性 |
|---|---|
| abstract | 必须使用,表明该类是抽象类 |
| public | 抽象类可以被任何其他类访问 |
| protected | 抽象类只能被同一包中的类和子类访问 |
| default(没有修饰符) | 抽象类只能被同一包中的类访问 |
| 抽象类不能使用的修饰符 | 不能使用的原因:破坏继承机制 |
| private | 抽象类需要被子类继承,而 private 访问级别不允许其他类访问 |
| final | final 类不能被继承,而抽象类需要被子类继承并实现其抽象方法 |
| static | 破坏了继承机制,因为static成员不能被子类继承和重写。将一个类标记为static意味着它不能被用作继承的基础,这与抽象类的设计目的 |
- 接口修饰符 :
2.成员变量
| 成员变量 | Abstract Class | Interface |
|---|---|---|
| 类型 | -与普通类一样,可以有普通成员变量,也可以有静态成员变量。 -可以有各种访问修饰符。 | -成员变量默认是 |
| 初始化 | -与普通类一样,成员变量可以在声明时初始化,或者在构造函数中初始化。 | -必须在声明时初始化,因为它们是 final 类型,且不能在接口的方法中修改 |
| 继承和使用 | -子类可以直接访问继承自抽象类的成员。 -抽象类可以包含已实现的方法,这些方法可以访问和操作抽象类中的成员变量。 | -实现接口的类无法直接修改接口中的常量,但可以访问这些常量。 -接口不能包含实例变量,因此也不能包含用于实例变量的初始化逻辑或构造函数。 |
3.方法
| 抽象类 | 接口 | |
|---|---|---|
| 构造方法 | 可有 | 不可以有 |
| 抽象方法 | 可有 | 可有 |
| 具体方法 | 可有 | 不可以有 |
| 静态方法 | 可有 | 可有,从Java8开始 |
| 默认方法 | 不可有 | 可有(必须用default修饰),从Java8开始 |
| 私有方法 | 可有 | 可有,从 Java 9 ,辅助静态方法、默认方法 |
细节:
1.接口中抽象方法默认使用public abstract修饰,不需要显式标注。
2.重写接口中的抽象方法时,必须使用也只能使用标识符public。
3.重写抽象类、接口的方法时,可以提高或不变访问权限,但不能降低。