当父类的某些方法需要声明,但又不确定如何实现时,就将其声明为抽象方法,包含抽象方法的类就是抽象类。
1. 抽象方法
用abstract修饰的方法,只有方法声明,没有方法体({}),语法格式:
访问修饰符 abstract 返回类型 方法名(参数列表);
2. 抽象类
用abstract修饰的类,语法格式:
访问修饰符 abstract class 类名 { // 类的成员(属性、方法、构造器等) }
3. 抽象类的使用规则
- 抽象类不能被实例化:无法直接
new Animal()创建对象,只能作为父类被继承。 - 抽象类可以没有抽象方法:但包含抽象方法的类必须声明为抽象类。
abstract只能修饰类和方法:不能修饰属性、构造器等其他元素。- 抽象方法不能有方法体:
abstract void aaa(){}是语法错误。 - 抽象方法的修饰限制:不能用
private、final、static修饰,因为这些关键字与重写冲突:private:子类无法访问,无法重写final:方法不能被重写static:方法属于类,不依赖对象,无法重写- 如果一个类继承了抽象类,必须实现抽象类的所有抽象方法,除非这个子类自己也声明为
abstract类。
// 抽象父类 abstract class Animal { public abstract void cry(); } // 普通子类:必须实现所有抽象方法 class Cat extends Animal { @Override public void cry() { System.out.println("小猫喵喵叫"); } } // 抽象子类:可以不实现,继续留给子类实现 abstract class Dog extends Animal {}抽象类本质还是类,可以包含任意成员:
- 非抽象方法(普通方法)
- 构造器(用于子类调用
super()初始化) - 静态属性、静态方法
- 普通属性等
4. 抽象类的应用:模版设计模式
抽象类是模板设计模式的核心实现:抽象类作为多个子类的通用模板,封装确定的通用逻辑,将不确定的可变逻辑声明为抽象方法,交给子类实现。
4.1 举例
模板抽象类(固定流程 + 可变任务)
// 抽象模板类:封装固定的计时流程,任务逻辑交给子类实现 abstract class TaskTemplate { // 固定流程:统计任务耗时(通用逻辑,子类不可修改) public final void calculateTime() { long start = System.currentTimeMillis(); job(); // 调用抽象方法:子类实现具体任务 long end = System.currentTimeMillis(); System.out.println("任务耗时:" + (end - start) + "ms"); } // 抽象方法:子类实现具体任务(可变逻辑) public abstract void job(); }子类实现(只写任务逻辑,复用计时流程)
// 子类1:数组排序任务 class SortTask extends TaskTemplate { @Override public void job() { // 具体排序逻辑(省略) int[] arr = new int[100000]; for (int i = 0; i < arr.length; i++) { arr[i] = (int) (Math.random() * 100000); } Arrays.sort(arr); } } // 子类2:循环打印任务 class PrintTask extends TaskTemplate { @Override public void job() { // 具体打印逻辑 for (int i = 0; i < 10000; i++) { System.out.print(""); } } }测试类
public class TestTemplate { public static void main(String[] args) { TaskTemplate sortTask = new SortTask(); sortTask.calculateTime(); // 自动统计排序耗时 TaskTemplate printTask = new PrintTask(); printTask.calculateTime(); // 自动统计打印耗时 } }