抽象类
- 定义
定义抽象类的时候需要用到关键字 abstract,放在 class 关键字前。关于抽象类的命名,《阿里的 Java 开发手册》上有强调,“抽象类命名要使用 Abstract 或 Base 开头”,这条规约还是值得遵守的,真正做到名如其意。
- 语法规则
- 抽象类不能被实例化,需要子类继承实现
- 抽象类应该至少有一个抽象方法
- 抽象类中既可以定义抽象方法,也可以定义普通方法
- 子类继承抽象父类,必须重写实现抽象父类的抽象方法
- 抽象类中的抽象方法没有方法体
接口
- 定义
接口通过 interface 关键字来定义,它可以包含一些常量和方法public interface Electronic { // 常量 String LED = "LED"; // 抽象方法 int getElectricityUse(); // 静态方法 static boolean isEnergyEfficient(String electtronicType) { return electtronicType.equals(LED); } // 默认方法 default void printDescription() { System.out.println("电子"); } }
- 语法规则
- 接口中定义的变量会在编译的时候自动加上
public static final
修饰符 - 没有使用
private
、default
或者static
关键字修饰的方法是隐式抽象的,在编译的时候会自动加上public abstract
修饰符。所以接口中的值无法改变。 - 从 Java 8 开始,接口中允许有静态方法,静态方法无法由(实现了该接口的)类的对象调用,它只能通过接口名来调用。目的是为了提供一种简单的机制,使我们不必创建对象就能调用方法
- 从 Java 8 开始,接口中允许定义 default 方法。它始终由一个代码块组成,为实现该接口而不覆盖该方法的类提供默认实现。
为什么要在接口中定义默认方法呢?
一个接口可能有多个实现类,这些类就必须实现接口中定义的抽象类,否则编译器就会报错。假如我们需要在所有的实现类中追加某个具体的方法,在没有 default 方法的帮助下,我们就必须挨个对实现类进行修改。 - 接口不允许直接实例化,需要定义一个类去实现接口
- 接口可以是空的,既可以不定义变量,也可以不定义方法,称为标志接口。比如Serializable 接口
- 不要在定义接口的时候使用 final 关键字,否则会报编译错误,因为接口就是为了让子类实现的,而 final 阻止了这种行为。
- 接口的抽象方法不能是 private、protected 或者 final,否则编译器都会报错。
- 接口的作用
- 使某些实现类具有我们想要的功能,比如继承一个Cloneable 接口就能进行拷贝了。
- Java 原则上只支持单一继承,但通过接口可以实现多重继承的目的。
- 实现多态
之前说过多态的构成条件:
1. 存在继承关系
2. 子类重写父类方法
3. 父类型引用指向子类型对象
由于接口需要其他类实现,也相当于是一种继承关系,因此也可以构成多态。
接口的常用三种设计模式
策略模式
适配器模式
工厂模式
抽象类和接口的区别
- 抽象类可以包含具体方法的实现;而在接口中,方法默认是 public abstract 的,但从 Java 8 开始,接口也可以包含有实现的默认方法和静态方法。
- 接口中的成员变量隐式为static final,但抽象类不是的
- 接口中不能含有静态代码块,而抽象类可以有静态代码块;
- 一个类可以实现多个接口,但只能继承一个抽象类
注:本文章来源自博主沉默王二的二哥的Java进阶之路学习内容。