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

news2024/11/17 0:41:40

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

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

黑马程序员免费预约咨询

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

神经网络与深度学习——第4章 前馈神经网络

本文讨论的内容参考自《神经网络与深度学习》https://nndl.github.io/ 第4章 前馈神经网络 前馈神经网络 神经元 Sigmoid型函数 Hard-Logistic函数和Hard-Tanh函数 ReLU函数 带泄露的ReLU 带参数的ReLU ELU函数 Softplus函数 Swish函数 GELU函数 Maxout单元 网络结构 前馈网络…

JAVAEE之多线程进阶(2)_ CAS概念、实现原理、ABA问题及解决方案

前言 在并发编程时,常常会出现线程安全问题,那么如何保证原子性呢?常用的方法就是加锁。在Java语言中可以使用 Synchronized和CAS实现加锁效果。  Synchronized关键字保证同步的,这会导致有锁,但是锁机制存在以下问题…

当你想使用预测概率作为预测模型的结果

🌟当你想使用预测概率作为医学预测模型的结果🌟 分类预测模型的预测结果有两种。一种是直接判断是哪一类,这种情况下唯一可以调节的就是决策阈值,或者是默认的0.5,也可以是参数确定的决策阈值,比如约登指数…

ELK 使用 metricbeat监控数据

IP功能版本192.168.140.153elk-18.13.4192.168.140.153metricbeat8.13.4192.168.140.156elk-28.13.4192.168.140.156metricbeat8.13.4192.168.140.159logstash8.13.4192.168.140.159kibana8.13.4 一、安装ELK 参考文档: https://download.csdn.net/download/weix…

Spring 源码:深度解析AOP源码配置解析

文章目录 一、 解析AOP配置的入口1.1 从XML配置到AOP Namespace的解析流程1.2 分析注解驱动的AOP配置解析流程 二、AOP配置解析的核心流程2.1 ConfigBeanDefinitionParser 类2.2 parse()2.3 parseAdvisor()2.4 parseAspect()2.5 parsePointcut()2.6 createAdvisorBeanDefinitio…

CentOS 7基础操作02_优化Linux操作系统中的服务

1、实验环境 公司在文件服务器中新安装了CentOS系统.由于默认启动的服务程序较多,系统运行缓慢。现需要对系绞服务进行适当优化,减少一些不必要的自启动服务.并设置系统在开机后直接进入字符模式。 2、需求描述 根据实际使用需求对CentOS 7操作系统中的…

C++第二十二弹---vector深度剖析及模拟实现(下)

✨个人主页: 熬夜学编程的小林 💗系列专栏: 【C语言详解】 【数据结构详解】【C详解】 目录 1、容量操作 2、内容修改操作 3、打印函数 4、迭代器失效 4.1、什么是迭代器失效 4.2、哪些操作会引起迭代器失效 总结 1、容量操作 size()…

【Docker】宝塔创建Docker容器配置nginx

前言 本篇是我入门docker的第一篇,由于docker具有很好的移植性,易于安装,开箱即用;签约的公司项目开发需要我进行学习,否则money减半,5555~ 百度找了一圈,只有关于docker怎么装宝塔服务器的却没…

从Socket到WebSocket

前言 不知道大家在学习网络编程的时候都是怎样的一种方式,我谨以此文章来记录我自己从头开始学习C网络编程时的经历,中间有许多我自己的一些想法和思考。当然作为一个刚开始学习的新手来说,有些内容也许不那么正确,只是代表了我在…

【Qt知识】Qt Creator快捷键

以下是Qt Creator中的一些常用快捷键列表(持续更新): 基本编辑 多行注释/取消多行注释: Ctrl /编译工程: Ctrl B运行工程: Ctrl R整行上移/下移: Ctrl Shift ↑/↓查找: Ctrl F函数声明和定义切换: F2向下查找: F3头文件和源文件切换:…

SAPUI5基础知识3 - 引导过程(Bootstrap)

1. 背景 在上一篇博客中,我们已经建立出了第一个SAPUI5项目,接下来,我们将为这个项目添加引导过程。 在动手练习之前,让我们先解释一下什么引导过程。 1.1 什么是引导过程? 在计算机科学中,引导过程也称…

苹果如何设置自动循环壁纸?这几种不同的方法你要学会

在使用手机的时候,我们可能会经常更换手机壁纸,遇见好看或者有意义的图片时就想将其设置为壁纸,你知道 iPhone 手机可以设置自动循环壁纸吗?如果你不了解下面就带你一起看看 iPhone 手机如何设置壁纸自动循环。 壁纸程序设置 想…

GIS之arcgis系列06:线划图缓冲区分析

缓冲区工具将在输入要素周围指定距离内创建缓冲区面。 缓冲区例程将遍历输入要素的每个折点并创建缓冲区偏移。 通过这些偏移创建输出缓冲区要素 原理: 01.打开文件 02.确定单位,在文件属性里。 03.工具箱-->分析工具-->邻域分析-->缓冲区。 …

藏汉翻译通小程序——你口袋里的藏语翻译助手!支持高精度藏文OCR文字识别提取,安卓iPhone手机都能用的藏汉翻译小助手!

想要快速学习藏语或者与藏族朋友无障碍沟通吗?藏汉翻译通小程序绝对是你的不二之选! 这款小程序不仅界面简洁、操作便捷,更重要的是它集合了多种实用功能于一身。 双语翻译:无论你是藏族还是汉族,只需输入文字&#…

C#中的实体属性详解与示例

文章目录 实体属性的定义实体属性的访问实体属性的示例总结 在C#中,实体属性是面向对象编程的重要组成部分。实体属性允许我们定义对象的特征和行为,并提供了一种方式来访问和管理这些特征。通过实体属性,我们可以封装对象的状态,…

【Linux】Linux基本指令3

目录 1.date指令 2.cal指令 3.find指令:(灰常重要) -name 4.grep指令——行文本过滤工具 5.zip/unzip指令: 6.tar指令(重要):打包/解包,不打开它,直接看内容 7.bc…

OSPF学习笔记(状态机)

1、邻居关系 OSPF设备启动后,会通过OSPF接口向外发送Hello报文,收到Hello报文的OSPF设备会检查报文中所定义的参数,如果双方一致就会形成邻居关系,两端设备互为邻居 2、邻接关系 形成邻居关系后,如果两端设备成功交…

Spring boot集成通义千问大模型

Spring boot集成通义千问大模型 背景 我在用idea进行java开发时发现了通义灵码这款免费的智能代码补全插件,用了一段时间了,感觉很不错。就想着在自己的项目中也能集成通义千问大模型实现智能回答,毕竟对接openai需要解决网络问题&#xff…

[学习笔记]知乎文章-PyTorch的Transformer

参考资料: PyTorch的Transformer register_buffer的作用是:登记成员变量,它会自动成为模型中的参数,随着模型移动(gpu/cpu)而移动,但是不会随着梯度进行更新。 参考资料:【Torch API…

【云原生】kubernetes中pod的生命周期、探测钩子的实战应用案例解析

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,…