跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Javajava

Java 抽象类详解:概念、特性与代码示例

系统讲解了 Java 抽象类的基础知识与应用。首先定义了抽象方法与抽象类,强调抽象类不能实例化且包含抽象方法时必须声明为 abstract。接着阐述了抽象类的设计思想,即通过抽取共性行为定义规范,强制子类实现特定逻辑。文中详细说明了继承抽象类的两种策略:重写所有抽象方法成为具体类,或保持抽象状态继续被继承。此外,对比了抽象类与普通类、接口在实例化、方法、构造方法及成员变量上的差异。最后提供了完整的 Java 代码示例,涵盖 Animal、Cat、Dog 等类的继承关系,以及结合接口 Swim 的多态性演示,帮助读者理解面向抽象编程的核心价值。

t ag发布于 2026/3/22更新于 2026/9/1072 浏览

抽象类 (Abstract Class)

一、抽象类的基本概念

1. 抽象方法

  • 定义:一个没有方法体的方法(即只有方法声明,没有具体的实现)。
  • 格式:public abstract 返回值类型 方法名 (参数列表);
  • 特点:
    • 使用 abstract 关键字修饰。
    • 没有方法体,直接以分号 ; 结束。
    • 它定义了一个'必须实现'的规范或契约。

2. 抽象类

  • 定义:包含抽象方法的类必须被声明为抽象类。
  • 格式:public abstract class 类名 { // 类的内容 }
  • 特点:
    • 使用 abstract 关键字修饰类。
    • 抽象类不能直接实例化(不能 new 抽象类)。

二、抽象类的作用与设计思想

抽象类的核心是一种'未完成'的类设计模板。

  1. 抽取共性,定义规范:
    • 当在父类中提取多个子类的共性行为时,如果无法(或不适合)确定该行为的具体实现,就将该方法声明为抽象方法。
    • 这样,抽象类就定义了一个'规范'或'契约',强制所有非抽象的子类必须按照这个声明来提供具体的实现。
  2. 强制子类重写:
    • 子类继承抽象类后,必须处理这些抽象方法。这保证了代码的一致性。

通俗理解:抽象类就像是制定了一份'必须完成的任务清单'。清单上只写了任务名称和要求(抽象方法),但没写怎么做。子类就像不同的执行者,它们必须按照清单完成所有任务(实现所有抽象方法),但可以根据自己的情况选择不同的完成方式。

三、继承抽象类的注意事项

当一个普通类继承一个抽象类时,有两种选择:

  1. 重写所有抽象方法(推荐,也是最常见的情况)
    • 将父类中定义的所有抽象方法都提供具体的实现。
    • 这样,子类就成为了一个'具体类',可以被正常实例化。
  2. 将自己也声明为抽象类
    • 如果子类没有重写或没有重写全部的抽象方法,那么这个子类也必须用 abstract 关键字修饰,成为一个新的抽象类。
    • 这个新的抽象类可以继续被其他类继承。

简单总结:'抽象'具有传递性。一个类只要继承了抽象方法而没有实现它,它自己就必须保持抽象。

四、抽象类的其他特性

  1. 抽象类中可以有构造方法:

    public abstract class Animal {
        private String name;
        // 抽象类可以有构造方法
          {
            .name = name;
        }
         String  {
             name;
        }
           ;
    }
    
public
Animal
(String name)
this
public
getName
()
return
public
abstract
void
eat
()
  • 虽然抽象类不能直接实例化,但它可以有构造方法。
  • 构造方法用于子类创建对象时,初始化从父类继承来的成员。
  • 抽象类中不一定有抽象方法:

    public abstract class MyBaseClass {
        // 没有抽象方法,但类依然是抽象的
        public void normalMethod() {
            System.out.println("这是一个普通方法");
        }
    }
    // 这个类不能 new MyBaseClass(),只能被继承。
    
    • 一个类被 abstract 修饰,它就是抽象类。
    • 但抽象类不一定包含抽象方法。这种设计通常是为了防止这个类被实例化,而只允许它被继承。
  • 抽象类中可以包含普通成员:

    • 抽象类可以有普通的成员变量和普通的成员方法(非抽象方法)。
    • 这些普通成员可以直接被子类继承和使用。
  • 五、完整示例

    // 1. 定义抽象类
    public abstract class Animal {
        private String name;
        private int age;
        
        // 抽象类可以有构造方法
        public Animal(String name, int age) {
            this.name = name;
            this.age = age;
        }
        
        // 抽象方法:定义了一个必须完成的行为规范
        public abstract void eat();
        
        // 普通方法:子类可以直接继承使用
        public void sleep() {
            System.out.println(name + "正在睡觉");
        }
        
        // Getter/Setter
        public String getName() {
            return name;
        }
        
        public int getAge() {
            return age;
        }
    }
    
    // 2. 具体子类:必须重写所有抽象方法
    public class Cat extends Animal {
        public Cat(String name, int age) {
            super(name, age); // 调用父类构造方法
        }
        
        @Override
        public void eat() {
            System.out.println(getName() + "(" + getAge() + "岁)正在吃鱼");
        }
    }
    
    // 3. 另一个具体子类
    public class Dog extends Animal {
        public Dog(String name, int age) {
            super(name, age);
        }
        
        @Override
        public void eat() {
            System.out.println(getName() + "(" + getAge() + "岁)正在啃骨头");
        }
        
        // 子类可以有自己的特有方法
        public void watchHouse() {
            System.out.println(getName() + "在看家");
        }
    }
    
    // 4. 测试类
    public class Test {
        public static void main(String[] args) {
            // Animal a = new Animal(); // 错误!抽象类不能实例化
            Animal cat = new Cat("小花", 2);
            cat.eat(); // 输出:小花(2 岁)正在吃鱼
            cat.sleep(); // 输出:小花正在睡觉
            
            Dog dog = new Dog("大黄", 3);
            dog.eat(); // 输出:大黄(3 岁)正在啃骨头
            dog.watchHouse(); // 输出:大黄在看家
        }
    }
    
    // 5. 抽象子类示例(不重写抽象方法)
    public abstract class Bird extends Animal {
        // 没有重写 eat() 方法,所以 Bird 也必须是抽象类
        public Bird(String name, int age) {
            super(name, age);
        }
        
        // 可以定义新的抽象方法
        public abstract void fly();
    }
    
    // 6. 最终的具体类,需要实现所有抽象方法(包括 Animal 的和 Bird 的)
    public class Sparrow extends Bird {
        public Sparrow(String name, int age) {
            super(name, age);
        }
        
        @Override
        public void eat() {
            // 实现 Animal 的 eat()
            System.out.println(getName() + "正在吃虫子");
        }
        
        @Override
        public void fly() {
            // 实现 Bird 的 fly()
            System.out.println(getName() + "正在飞翔");
        }
    }
    

    六、抽象类 vs 普通类 vs 接口

    特性普通类抽象类接口
    实例化可以直接实例化不能直接实例化不能直接实例化
    方法全是具体方法可以有具体方法和抽象方法Java 8 前全是抽象方法,之后可以有默认/静态方法
    构造方法有有没有
    成员变量任意类型任意类型只能是 public static final 常量
    继承/实现单继承单继承多实现
    设计目的具体实现模板设计,部分实现,部分规范纯规范,定义行为契约

    七、总结

    1. 抽象类是一个'半成品'类,它定义了部分实现,也声明了部分必须由子类完成的规范(抽象方法)。
    2. 核心作用:代码复用 + 强制规范。既提取了共性代码,又强制子类必须实现特定行为。
    3. 使用场景:当多个相关类有共同的属性和行为,但某些行为的具体实现各不相同时。
    4. 设计理念:'面向抽象编程',依赖于抽象(父类或接口)而非具体实现,提高了代码的灵活性和可扩展性。

    八、完整项目代码示例

    以下展示了结合接口 Swim 的完整项目结构:

    package abstract02;
    
    public class Test {
        public static void main(String[] args) {
            Frog f = new Frog(1, "wawa");
            System.out.println(f.getName() + ", " + f.getAge());
            f.drink();
            f.eat();
            f.swim();
            
            Dog d = new Dog(5, "wangwang");
            System.out.println(d.getName() + ", " + d.getAge());
            d.drink();
            d.eat();
            d.swim();
            
            Sheep s = new Sheep(6, "miemie");
            System.out.println(s.getName() + ", " + s.getAge());
            s.drink();
            s.eat();
        }
    }
    
    package abstract02;
    
    public abstract class Animal {
        private String name;
        private int age;
        
        public Animal() {
        }
        
        public Animal(int age, String name) {
            this.age = age;
            this.name = name;
        }
        
        public int getAge() {
            return age;
        }
        
        public void setAge(int age) {
            this.age = age;
        }
        
        public String getName() {
            return name;
        }
        
        public void setName(String name) {
            this.name = name;
        }
        
        public void drink() {
            System.out.println("动物在喝水");
        }
        
        public abstract void eat();
    }
    
    package abstract02;
    
    public class Dog extends Animal implements Swim {
        public Dog() {
        }
        
        public Dog(int age, String name) {
            super(age, name);
        }
        
        @Override
        public void eat() {
            System.out.println("狗在吃骨头");
        }
        
        @Override
        public void swim() {
            System.out.println("狗在游泳");
        }
    }
    
    package abstract02;
    
    public class Frog extends Animal implements Swim {
        public Frog() {
        }
        
        public Frog(int age, String name) {
            super(age, name);
        }
        
        @Override
        public void eat() {
            System.out.println("青蛙在吃虫子");
        }
        
        @Override
        public void swim() {
            System.out.println("青蛙在游泳");
        }
    }
    
    package abstract02;
    
    public class Sheep extends Animal {
        public Sheep() {
        }
        
        public Sheep(int age, String name) {
            super(age, name);
        }
        
        @Override
        public void eat() {
            System.out.println("🐏在吃草");
        }
    }
    
    package abstract02;
    
    public interface Swim {
        public abstract void swim();
    }
    

    目录

    1. 抽象类 (Abstract Class)
    2. 一、抽象类的基本概念
    3. 1. 抽象方法
    4. 2. 抽象类
    5. 二、抽象类的作用与设计思想
    6. 三、继承抽象类的注意事项
    7. 四、抽象类的其他特性
    8. 五、完整示例
    9. 六、抽象类 vs 普通类 vs 接口
    10. 七、总结
    11. 八、完整项目代码示例

    更多推荐文章

    查看全部
    • WebGIS 项目实战经验与技术应用展望
    • Java 虚拟机内存模型详解
    • 单链表去重:保留首次出现的绝对值节点
    • Python 基础:容器公共操作与推导式详解
    • 清华论文:大规模基础模型在预测与健康管理(PHM)中的应用研究
    • AI 大模型 Agent 面试精选 15 题:基础概念与框架
    • VS Code 运行前端代码教程
    • C++ STL vector 容器模拟实现详解
    • Llama API 集成示例:文本补全与函数调用
    • 算法:缺失的第一个正数(LeetCode 41)
    • DREAM 数据库:脑电与梦境配对开启意识研究大数据时代
    • Flutter 三方库 shelf_modular 的鸿蒙化适配指南
    • 35 道常见前端 Vue 面试题解析
    • AIRI:基于 AI 大模型构建桌宠虚拟伴侣
    • Capacitor 跨平台打包工具实战指南
    • OpenClaw 搭建个性化私人 AI 助手完整配置指南
    • C++ 搜索引擎核心:基于正倒排索引的 Searcher 实现解析
    • 数据分析师的核心职责与工作流程解析
    • VS Code 中实现 Go 语言自动导包配置指南
    • Web 开发者构建多模态 Agent 图像识别技能的全栈实战

    相关免费在线工具

    • Keycode 信息

      查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

    • Escape 与 Native 编解码

      JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

    • JavaScript / HTML 格式化

      使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

    • JavaScript 压缩与混淆

      Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

    • Base64 字符串编码/解码

      将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

    • Base64 文件转换器

      将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online