Java 抽象类详解

 更新时间:2026年03月18日 09:15:47   作者:数据与人文  
抽象类是用abstract关键字修饰的类,其核心作用是作为父类提供通用模板,同时强制子类实现特定方法,本文介绍Java 抽象类的相关知识,感兴趣的朋友跟随小编一起看看吧

一、抽象类的基本定义

抽象类是用abstract关键字修饰的类,其核心作用是作为父类提供通用模板,同时强制子类实现特定方法。

1. 语法格式

// 定义抽象类
abstract class 类名 {
    // 成员变量
    // 构造方法(抽象类可以有构造方法)
    // 具体方法(有方法体)
    // 抽象方法(无方法体,用abstract修饰)
    abstract 返回值类型 方法名(参数列表);
}

2. 关键特征

  • 不能实例化:抽象类无法通过new关键字创建对象(编译报错),只能作为父类被继承。
  • 可包含抽象方法:抽象方法是没有方法体的方法(用abstract修饰),必须由子类实现。
  • 可包含普通成员:抽象类可以有成员变量、构造方法、普通方法(有实现)、静态方法等,与普通类的区别仅在于 “可包含抽象方法” 和 “不能实例化”。

二、抽象方法的规则

抽象方法是抽象类的核心组成部分,它定义了子类必须实现的 “规范”,其声明有严格规则:

  • 必须用abstract修饰,且没有方法体(不写{},直接用;结束)。
    • 示例:abstract void run();(正确);abstract void run() {}(错误,不能有方法体)。
  • 不能被privatefinalstatic修饰:
    • private:抽象方法需要被子类重写,private会阻止子类访问,矛盾。
    • finalfinal方法不能被重写,而抽象方法必须被重写,矛盾。
    • staticstatic方法属于类,无法被实例方法重写(子类的静态方法不能重写父类的静态方法)。
  • 抽象类中可以没有抽象方法,但有抽象方法的类必须是抽象类。
  • (若一个类包含抽象方法却不用abstract修饰,编译报错)。

三、抽象类与子类的关系

子类继承抽象类时,必须遵循以下规则:

  • 子类必须实现抽象类中所有的抽象方法,否则子类必须也声明为抽象类(用abstract修饰)。
  • 示例:
// 抽象父类
abstract class Animal {
    // 抽象方法:所有动物都必须实现“吃”的行为
    abstract void eat();
    // 普通方法:所有动物共有的“睡觉”行为
    void sleep() {
        System.out.println("动物睡觉");
    }
}
// 子类Dog:非抽象类,必须实现eat()
class Dog extends Animal {
    @Override
    void eat() { // 实现抽象方法
        System.out.println("狗吃骨头");
    }
}
// 子类Bird:若不实现eat(),则必须声明为抽象类
abstract class Bird extends Animal {
    // 未实现eat(),因此Bird必须是抽象类
}
  • 子类实现抽象方法时,访问权限不能低于父类
  • 例如:父类抽象方法为protected void eat(),子类实现时不能用private(可⽤protectedpublic)。
  • 抽象类的构造方法
  • 抽象类可以有构造方法(用于初始化自身成员变量),但不能直接调用(因无法实例化)。子类实例化时,会先调用抽象父类的构造方法(遵循 “先父后子” 的初始化顺序)。

示例:

abstract class Vehicle {
    protected String brand;
    // 抽象类的构造方法
    public Vehicle(String brand) {
        this.brand = brand;
    }
    abstract void drive();
}
class Car extends Vehicle {
    public Car(String brand) {
        super(brand); // 调用父类构造方法
    }
    @Override
    void drive() {
        System.out.println(brand + "汽车行驶");
    }
}
// 测试
public class Test {
    public static void main(String[] args) {
        Car car = new Car("宝马"); // 子类实例化时,先调用Vehicle的构造方法
        car.drive(); // 输出:宝马汽车行驶
    }
}

四、抽象类 vs 接口:核心区别

抽象类和接口(Interface)都能定义规范,但在设计目的和使用场景上有本质区别:

维度抽象类(Abstract Class)接口(Interface)
继承关系单继承(子类只能继承一个抽象类)多实现(类可以实现多个接口)
方法类型可包含抽象方法、普通方法、静态方法、默认方法Java 8 前:只能有抽象方法;Java 8 后:可包含默认方法(default)、静态方法
成员变量可包含各种修饰符的成员变量(privateprotectedpublic等)只能是public static final修饰的常量(默认,可省略)
构造方法有构造方法(供子类调用)无构造方法
设计目的体现 “is-a” 关系(继承共性),强调代码复用体现 “like-a” 关系(实现能力),强调行为规范

示例:何时用抽象类,何时用接口?

  • 若需要为一组相关类提供通用实现(如Animal类的sleep()方法),同时强制子类实现特定行为(如eat()),用抽象类
  • 若需要定义一组不相关类的共同行为(如Flyable接口,让BirdPlane都能实现 “飞”),用接口

五、抽象类的使用场景

抽象类适合以下场景:

  • 提取共性,减少重复代码:当多个子类有相同的方法实现时,将这些实现放在抽象父类中,子类只需关注自身特有的实现。
  • 例如:Shape抽象类定义通用的getColor()方法,子类CircleRectangle只需实现getArea()(面积计算因形状而异)。
  • 定义模板方法:通过 “模板方法模式”,在抽象类中定义算法骨架,将可变步骤延迟到子类实现。
  • 示例:
// 抽象类:定义泡茶/泡咖啡的通用流程
abstract class Beverage {
    // 模板方法:固定流程(不能被重写)
    public final void prepare() {
        boilWater();    // 共性步骤:烧水
        brew();         // 抽象步骤:冲泡(子类实现)
        pourInCup();    // 共性步骤:倒入杯子
        addCondiments();// 抽象步骤:加调料(子类实现)
    }
    // 抽象方法:子类实现具体冲泡方式
    abstract void brew();
    // 抽象方法:子类实现具体加调料方式
    abstract void addCondiments();
    // 共性方法:烧水
    void boilWater() {
        System.out.println("烧开水");
    }
    // 共性方法:倒入杯子
    void pourInCup() {
        System.out.println("倒入杯子");
    }
}
// 子类:咖啡
class Coffee extends Beverage {
    @Override
    void brew() {
        System.out.println("冲泡咖啡粉");
    }
    @Override
    void addCondiments() {
        System.out.println("加牛奶和糖");
    }
}
  • 限制实例化:当某个类仅作为父类存在(无需实例化),用抽象类阻止其被new创建。

六、注意事项

  1. 抽象类不能用final修饰:final类不能被继承,而抽象类必须被继承才能使用,二者矛盾。
  2. 抽象类可以继承普通类或抽象类:抽象类的父类可以是普通类(如abstract class A extends BB是普通类)。
  3. 抽象类可以实现接口:抽象类实现接口时,无需实现接口的抽象方法(可延迟到子类实现)。

到此这篇关于Java 抽象类详解的文章就介绍到这了,更多相关Java 抽象类内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java如何实现Word文档分栏效果

    Java如何实现Word文档分栏效果

    这篇文章主要介绍了Java如何实现Word文档分栏效果,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-05-05
  • 懒人 IDEA 插件推荐: EasyCode 一键帮你生成所需代码(Easycode用法)

    懒人 IDEA 插件推荐: EasyCode 一键帮你生成所需代码(Easycode用法)

    这篇文章主要介绍了懒人 IDEA 插件推荐: EasyCode 一键帮你生成所需代码,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-08-08
  • Golang Protocol Buffer案例详解

    Golang Protocol Buffer案例详解

    这篇文章主要介绍了Golang Protocol Buffer案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-08-08
  • 解决@RequestBody接收json对象报错415的问题

    解决@RequestBody接收json对象报错415的问题

    这篇文章主要介绍了解决@RequestBody接收json对象报错415的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-06-06
  • Java线程之ThreadLocal解析

    Java线程之ThreadLocal解析

    这篇文章主要介绍了Java线程之ThreadLocal解析,ThreadLocal 提供线程的局部变量,每个线程都可以通过get()和set()对局部变量进行操作而不会对其他线程的局部变量产生影响,实现了线程之间的数据隔离,需要的朋友可以参考下
    2023-09-09
  • Java并发编程之详解CyclicBarrier线程同步

    Java并发编程之详解CyclicBarrier线程同步

    在之前的文章中已经为大家介绍了java并发编程的工具:BlockingQueue接口,ArrayBlockingQueue,DelayQueue,LinkedBlockingQueue,PriorityBlockingQueue,SynchronousQueue,BlockingDeque接口,ConcurrentHashMap,CountDownLatch,本文为系列文章第十篇,需要的朋友可以参考下
    2021-06-06
  • SpringBoot集成Druid连接池进行SQL监控的问题解析

    SpringBoot集成Druid连接池进行SQL监控的问题解析

    这篇文章主要介绍了SpringBoot集成Druid连接池进行SQL监控的问题解析,在SpringBoot工程中引入Druid连接池非常简单,本文通过实例代码给大家介绍的非常详细,需要的朋友可以参考下
    2021-07-07
  • java中注解的实现原理详解

    java中注解的实现原理详解

    这篇文章主要介绍了java中注解的实现原理详解,注解也叫元数据,例如我们常见的@Override和@Deprecated,注解是JDK1.5版本开始引入的一个特性,用于对代码进行说明,可以对包、类、接口、字段、方法参数、局部变量等进行注解,需要的朋友可以参考下
    2023-10-10
  • Spring Boot2.0实现静态资源版本控制详解

    Spring Boot2.0实现静态资源版本控制详解

    这篇文章主要给大家介绍了关于Spring Boot2.0实现静态资源版本控制的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-11-11
  • windows系统使用mvn命令打包并指定jdk路径方式

    windows系统使用mvn命令打包并指定jdk路径方式

    这篇文章主要介绍了windows系统使用mvn命令打包并指定jdk路径方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-04-04

最新评论