如何理解 Java 接口和抽象类的定义和使用场景

Java 是一种面向对象编程语言,提供了丰富的面向对象编程机制。其中,接口和抽象类是两个重要的概念,它们在设计和实现代码时扮演着关键的角色。

接口(Interface)

定义和特性

接口是 Java 中的一种引用数据类型,是抽象方法的集合。接口中的方法没有方法体(即没有具体的实现),接口中也可以包含常量(默认是 public static final)。接口是一种契约,规定了类必须提供的方法。以下是接口的一些主要特性:

  1. 接口中的方法默认是 publicabstract:所有在接口中声明的方法默认都是公开的和抽象的。
  2. 接口中的变量默认是 public static final:接口中声明的变量默认是常量。
  3. Java 8 引入了默认方法和静态方法:默认方法(default)允许在接口中提供方法的默认实现,静态方法(static)可以在接口中提供具体的静态方法实现。
  4. 接口不能包含实例字段:接口中只能包含常量,不能有实例变量。
  5. 多继承:一个类可以实现多个接口,这在 Java 中提供了一种多继承的方式。
使用场景

接口主要用于以下场景:

  1. 定义契约:接口用于定义类必须实现的方法,这对API设计尤为重要。通过接口,可以确保实现类提供必要的功能,而不限制其具体实现方式。
  2. 解耦:接口通过抽象层来解耦系统的不同部分,使得各部分可以独立开发和维护。
  3. 多态性:通过接口,可以实现对象的多态性。例如,可以用接口类型的引用指向实现类的实例,从而可以在运行时动态地决定具体的实现。
示例
// 定义一个接口
public interface Animal {
    void eat();
    void sleep();
}

// 实现接口的类
public class Dog implements Animal {
    @Override
    public void eat() {
        System.out.println("Dog is eating");
    }
    
    @Override
    public void sleep() {
        System.out.println("Dog is sleeping");
    }
}

抽象类(Abstract Class)

定义和特性

抽象类是包含一个或多个抽象方法的类。抽象类不能被实例化,只能被继承。抽象类中的抽象方法没有方法体,需要在子类中实现。以下是抽象类的一些主要特性:

  1. 抽象方法:抽象类可以包含抽象方法,这些方法没有实现,需要在子类中实现。
  2. 非抽象方法:抽象类也可以包含具体的方法(即有实现的方法)。
  3. 字段:抽象类可以包含字段,可以是实例字段或静态字段。
  4. 构造方法:抽象类可以有构造方法,尽管不能实例化,但构造方法可以被子类调用。
  5. 单继承:一个类只能继承一个抽象类。
使用场景

抽象类主要用于以下场景:

  1. 代码复用:抽象类可以包含具体的方法实现,这些方法可以被子类继承和使用,从而实现代码复用。
  2. 定义模板:抽象类可以定义模板方法,提供基本的算法结构,具体实现延迟到子类。
  3. 限制继承:抽象类可以作为基类,提供基本的功能和框架,但限制子类必须实现某些方法。
示例
// 定义一个抽象类
public abstract class Animal {
    public abstract void eat();
    public abstract void sleep();
    
    public void breathe() {
        System.out.println("Animal is breathing");
    }
}

// 实现抽象类的子类
public class Dog extends Animal {
    @Override
    public void eat() {
        System.out.println("Dog is eating");
    }
    
    @Override
    public void sleep() {
        System.out.println("Dog is sleeping");
    }
}

接口与抽象类的区别

  1. 目的不同:接口用于定义契约,提供一组方法规范,而抽象类用于代码复用和定义模板。
  2. 多继承:类可以实现多个接口,但只能继承一个抽象类。
  3. 成员:接口只能包含常量和抽象方法(Java 8之后可以有默认方法和静态方法),而抽象类可以包含字段、具体方法和抽象方法。
  4. 构造方法:接口不能有构造方法,而抽象类可以有构造方法。
  5. 访问修饰符:接口中的方法默认是 public,而抽象类中的方法可以有各种访问修饰符(publicprotectedprivate)。

使用场景对比

何时使用接口
  • 需要实现多继承:当一个类需要从多个来源继承行为时,接口是最佳选择。
  • 定义契约而非实现:当需要定义一个行为规范而不关心具体实现时,使用接口。
  • 解耦:接口可以用于解耦代码,实现低耦合高内聚。
何时使用抽象类
  • 代码复用:当多个类有共同的行为或属性时,可以使用抽象类来提供这些通用代码。
  • 定义模板方法:当需要定义一个基本算法的骨架,并允许子类实现具体步骤时,使用抽象类。
  • 需要构造函数:当类需要初始化某些状态或执行某些操作时,可以使用抽象类提供构造函数。

实际应用中的选择

在实际应用中,接口和抽象类的选择通常取决于具体的需求和设计目标。以下是一些实际应用中的考虑因素:

  1. 扩展性:如果预期某个类层次结构会频繁扩展,引入新功能,那么接口提供的灵活性和多继承能力更适合。
  2. 现有类的改造:如果需要对现有类进行改造,使其符合新的接口规范,那么可以通过实现接口而不改变类的继承关系。
  3. 模板方法模式:当采用模板方法模式设计时,抽象类更适合,因为它可以提供基本的算法结构和部分实现。
  4. 性能:在某些情况下,抽象类可能比接口具有更好的性能,因为调用具体方法时可以避免接口调用的额外开销。

综合实例

为了更好地理解接口和抽象类的实际应用,以下是一个综合实例,展示如何在一个系统中同时使用接口和抽象类。

// 定义一个接口
public interface Movable {
    void move();
}

// 定义一个抽象类
public abstract class Vehicle implements Movable {
    protected String brand;
    protected String model;
    
    public Vehicle(String brand, String model) {
        this.brand = brand;
        this.model = model;
    }
    
    public void start() {
        System.out.println(brand + " " + model + " is starting");
    }
    
    public abstract void fuelUp();
}

// 定义一个具体的子类
public class Car extends Vehicle {
    public Car(String brand, String model) {
        super(brand, model);
    }
    
    @Override
    public void move() {
        System.out.println(brand + " " + model + " is moving");
    }
    
    @Override
    public void fuelUp() {
        System.out.println(brand + " " + model + " is fueling up");
    }
}

// 使用示例
public class Main {
    public static void main(String[] args) {
        Car car = new Car("Toyota", "Corolla");
        car.start();
        car.move();
        car.fuelUp();
    }
}

在这个综合实例中,我们定义了一个 Movable 接口和一个 Vehicle 抽象类。Vehicle 抽象类实现了 Movable 接口,并提供了一些通用的功能。具体的 Car 类继承了 Vehicle 抽象类,并实现了抽象方法 fuelUp 和接口方法 move

接口和抽象类是 Java 中两个重要的概念,它们在设计和实现代码时扮演着不同的角色。接口用于定义类必须实现的方法,提供了一种多继承的方式,适合用于解耦和定义契约。

抽象类用于提供部分实现和代码复用,适合用于定义模板方法和提供基础功能。在实际应用中,选择接口还是抽象类取决于具体的设计需求和目标。理解并灵活运用接口和抽象类,可以使代码更具扩展性、可维护性和可读性。

黑马程序员免费预约咨询

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/664056.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C++学习第十一天——vector的模拟实现

✨ 生于火焰,落俗不可避免,但浪漫至死不渝 🌏 📃个人主页:island1314 🔥个人专栏:C学习 🚀 欢迎关注:👍点赞 &…

eDP V1.4协议介绍

一、说明 eDP的全称是Embedded DisplayPort嵌入式显示端口,主要应用与短距离系统内应用,例如手机、一体式台式机等。eDP V1.4b是基于DP V1.3标准制作完成,但因应用场景的不同,还是有很多区别。 电压摆幅不同,eDP相对较低; eDP功耗相对较低; DP有线材和连接器的要求,eD…

JVM监控-JMX探针的安装和使用

jvm监控的搭建和使用 ​ Java Management Extensions(JMX)是一种Java标准,用于管理和监控Java应用程序,特别是分布式系统。它提供了一种标准化的方式来管理应用程序的各种方面,包括性能监控、配置更改、事件通知等。目…

Apache POI对Excel进行读写操作

1、什么是Apache POI ​ Apache POI 是一个处理Miscrosoft Office各种文件格式的开源项目。简单来说就是,我们可以使用 POI 在 Java 程序中对Miscrosoft Office各种文件进行读写操作。一般情况下,POI 都是用于操作 Excel 文件。 Apache POI 的应用场景&…

QT C++ 基于word模板 在书签位置写入文字和图片

如果你有按模版批量自动化操作word文件的需求,那么本文能给你一定的帮助。 它能满足你程序自动化生成报表的需求。常常用于上位机、测试仪器的软件中。 需要你你自己做个word模版文档,添加2个书签。点按钮,会按照你的模板文档生成一个同样的…

RK3588 AB镜像升级学习(一)

参考资料:Android A/B 系统_洛奇看世界的博客-CSDN博客 一、AB镜像分区 区分了OTA升级镜像的两种方式: 传统的升级方式:设备有Android系统和Recovery系统,如果Android需要升级时,把内容存到cache分区。重启后进入re…

GSM信令流程(附着、去附着、PDP激活、修改流程)

1、联合附着流程 附着包括身份认证、鉴权等 2、去附着流程 用户发起去附着 SGSN发起去附着 HLR发起去附着 GSSN使用S4发起去附着 3、Activation Procedures(PDP激活流程) 4、PDP更新或修改流程 5、Deactivate PDP Context 6、RAU(Routeing Area Update)流程 7、鉴权加…

Centos 7 安装刻录至硬件服务器

前言 在日常测试中,会遇到很多安装的场景,今天给大家讲一下centos 7 的安装,希望对大家有所帮助。 一.下载镜像 地址如下: centos官方镜像下载地址https://www.centos.org/download/ 按照需求依次点击下载 二.镜像刻录 镜像刻…

STM32---蓝牙模块ECB02(从机模式_与手机通信)

目录 1、ECB02 重点 参数 2、引脚说明 3、AT指令使用重点 4、使用USB转TTL模块测试 5、STM32开发板的接线 6、STM32通信代码 7、手机小程序 连接ECB02 1、ECB02 重点 参数 蓝牙协议: 5.2主从模式:主、从一体,可设置睡眠模式&#xff…

Jmeter压测中遇到的问题汇总

Jmeter使用过程问题总结 一、某个请求的请求体中有中文字段,执行后该请求无法成功 解决方法:在取样器的内容编码处加上UTF-8 二、遇到接口请求后报401,请求未授权(或者信息头管理器只写了cookie请求不成功) 解决方…

开展FMEA,这些准备工作你做足了吗?

在产品研发和制造过程中,失效模式与影响分析(FMEA)是一项至关重要的质量工具。它能够帮助团队提前识别和预防潜在的产品失效问题,从而提升产品的可靠性和质量。然而,要想充分发挥FMEA的效用,充分的准备工作…

全志H616(BIGTREETECH CB1)和 博通BCM2711(树莓派4B)CPU对比测试

一,实物对比图: BIGTREETECH CB1的底板接口的分布和树莓派4B是一样的,但是没有树莓派的音频接口,底板也不能放到树莓派4B的官方外壳里,因为底板的背面有一个DSI接口,高度超出了。 二,开发板硬…

【QEMU中文文档】1.关于QEMU

本文由 AI 翻译(ChatGPT-4)完成,并由作者进行人工校对。如有任何问题或建议,欢迎联系我。联系方式:jelin-shoutlook.com。 QEMU 是一款通用的开源机器仿真器和虚拟化器。 QEMU 可以通过几种不同的方式使用。最常见的用…

每日一题《leetcode--LCR 021.删除链表的倒数第N个结点》

https://leetcode.cn/problems/SLwz0R/ 这道题我们可以设一个哨兵位,然后把要遍历链表的结点指向该哨兵位。最后用for循环将指针指向要删除结点的前一个。 struct ListNode* removeNthFromEnd(struct ListNode* head, int n){struct ListNode* dummy malloc(sizeof…

[数据集][目标检测]RSNA肺炎检测数据集VOC+YOLO格式6012张1类别

数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):6012 标注数量(xml文件个数):6012 标注数量(txt文件个数):6012 标注…

一文读懂OrangePi AIpro体验测评与应用开发

文章目录 OrangePi AIpro 基本介绍AI边缘计算产品对比性能测试体验1. 点亮系统2. Jupyter远程启动测试官方例程3. 官方例程在OrangePi AIpro上的运行效果1. YOLOv5 目标检测2. OCR 识别3. ResNet50 物体检测4. 图像增强模型测试5 CartoonGAN 图像风格迁移 总结参考文档 OrangeP…

.NET SK 如何给AI大模型添加搜索引擎功能?

普通的AI大模型的数据都是在一开始训练的时候决定的&#xff0c;所以大模型的数据来源都可能存在时效性。 下面我们会利用SK插件来给AI大模型添加联网功能。 准备工作 创建一个名称为5_SK_Plugin_Web的控制台项目 复制以下代码到5_SK_Plugin_Web项目文件中 <Project Sdk…

taskENTER_CRITICAL()分析

1. 临界段代码 //任务级的临界段代码保护 taskENTER_CRITICAL() taskEXIT_CRITICAL()//中断级的临界段代码保护 taskENTER_CRITICAL_FROM_ISR() taskEXIT_CRITICAL_FROM_ISR()2. 以STM32为例 &#xff08;1&#xff09;STM32有0~15&#xff0c;共16级中断&#xff0c;可嵌套…

数据结构算法 数组的实现与练习(C语言实现,Java实现)

文章目录 数据结构数组(顺序表)特点使用Java实现更高级的数组C语言实现总结优点缺点 例题[26. 删除有序数组中的重复项](https://leetcode.cn/problems/remove-duplicates-from-sorted-array/)[1. 两数之和](https://leetcode.cn/problems/two-sum/)[27. 移除元素](https://lee…

教育数字展馆助力全球教育传播,科技引领数字化教育潮流

一、教育数字展馆助力教育传播 1、提高教育资源的可及性 教育数字展馆通过VR和WEB3D技术&#xff0c;将丰富的教育资源呈现在用户面前。不论是名校的经典课程&#xff0c;还是专家的精彩讲座&#xff0c;均可通过教育数字展馆实现线上展示。用户只需登录平台&#xff0c;即可…