一、抽象类和接口的主要区别表格
特性 | 抽象类 | 接口 |
---|---|---|
声明关键字 | 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.重写抽象类、接口的方法时,可以提高或不变访问权限,但不能降低。