Java 每日一刊(第14期):抽象类和接口

“抽象是所有能力的精髓。”

前言

这里是分享 Java 相关内容的专刊,每日一更。

本期将为大家带来以下内容:

  1. 抽象类
  2. 接口
  3. 抽象类和接口的区别
  4. 什么时候用抽象类,什么时候用接口
  5. 抽象类可以实现接口
  6. 接口中的常量其实是 public static final
  7. 标记接口(Marker Interface)
  8. 接口可以扩展多个接口
  9. 接口中的方法可以有多个默认实现来源

抽象类

抽象类是一种不能直接创建对象的类,它是一种模板,通常是为了给其他类用来继承的。抽象类可以包含两种方法:

  • 抽象方法:只有方法名称,没有具体的功能代码,子类必须要实现这些方法。
  • 具体方法:已经写好了功能代码的方法,子类可以直接用。

抽象类的特点

不能直接创建对象:你不能直接写 new Animal() 来创建一个抽象类的对象。它的主要作用是让其他类继承它。

可以有方法的具体实现:有一些方法在抽象类里已经实现了,所以子类可以直接用这些方法。

可以有构造方法:虽然你不能直接创建抽象类的对象,但你可以通过它的子类调用构造方法。

抽象类的例子

假设你想设计一个动物的类(Animal),但你不知道每种动物发出的声音是什么样的。所以你把 makeSound() 定义成一个抽象方法,让不同的动物自己去实现它。

// 抽象类使用 abstract 关键字定义
abstract class Animal {// 抽象方法,没有实现,需要子类去实现public abstract void makeSound();// 具体方法,子类可以直接使用public void sleep() {System.out.println("Sleeping...");}
}// 使用 extens 关键字继承自抽象类 Animal 的具体类
class Dog extends Animal {// 实现抽象方法@Overridepublic void makeSound() {System.out.println("Woof");}
}public class Test {public static void main(String[] args) {Animal dog = new Dog(); // 创建 Dog 对象dog.makeSound();        // 输出:Woofdog.sleep();            // 输出:Sleeping...}
}

解释:

  • Animal 类是抽象类,它定义了一个抽象方法 makeSound(),不同的动物发出的声音不同,所以这个方法没有实现。
  • Dog 类继承了 Animal 类,并实现了 makeSound() 方法。
  • sleep() 方法在抽象类里已经实现了,子类(如 Dog)可以直接使用它。

抽象类的使用场景

当你想要让多个类(例如不同的动物)共享一些相同的功能(如 sleep() 方法),但有些方法(如 makeSound())需要不同的实现时,你可以使用抽象类。

接口

接口是一种比抽象类更抽象的东西,它定义了一些方法,但这些方法都没有实现。类可以通过 implements 关键字来“实现”接口里的方法。

接口的特点

不能有具体方法:接口里的方法在 Java 8 之前都是空的,没有具体实现。它只告诉你这个方法应该存在,但具体怎么做由类自己决定。

可以多实现:一个类可以实现多个接口,而不像继承只能继承一个父类。

接口强调行为:接口更像是“契约”或“协议”,它规定了一个类应该具备哪些功能。

接口的例子

假设你想定义一种交通工具的接口(Vehicle),每种交通工具都应该有 start()stop() 方法,但你不需要知道每种交通工具具体是怎么启动或停止的,这由具体的交通工具类去实现。

// 使用 interface 关键字定义一个接口
interface Vehicle {// 接口中的方法都是抽象的,不需要写具体实现void start();void stop();
}// 使用 implements 关键字实现接口的具体类
class Car implements Vehicle {// 实现接口中的方法@Overridepublic void start() {System.out.println("Car is starting");}@Overridepublic void stop() {System.out.println("Car is stopping");}
}public class Test {public static void main(String[] args) {Vehicle car = new Car(); // 创建 Car 对象car.start();  // 输出:Car is startingcar.stop();   // 输出:Car is stopping}
}

解释:

  • Vehicle 是一个接口,它定义了 start()stop() 两个方法,但没有给出具体实现。
  • Car 类实现了 Vehicle 接口,并具体定义了这两个方法该怎么做。

接口的使用场景

当你希望不同的类(如汽车、飞机)有相同的行为(如 start()stop()),但它们的具体实现不同时,使用接口会更合适。

抽象类和接口的区别

对比点抽象类接口
定义可以包含抽象方法和具体方法只能包含抽象方法(Java 8 之后可以有默认方法)
成员变量可以包含成员变量只能包含常量(public static final
构造函数可以有构造函数不能有构造函数
继承关系只能继承一个抽象类可以实现多个接口
适用场景用于定义类的通用行为,提供部分实现用于定义类的行为规范,不提供实现
访问修饰符可以有不同的访问修饰符(publicprotected默认所有方法是 public

什么时候用抽象类,什么时候用接口

用抽象类的情况:如果你有一些功能是所有子类共享的,但某些功能需要子类去实现,这时抽象类比较合适。例如,所有的动物都会“睡觉”(sleep()),但发出的声音不同(makeSound())。

用接口的情况:如果你想为完全不同的类定义共同的行为,而不关心它们之间是否有继承关系,接口更合适。例如,汽车和飞机都是交通工具,都需要 start()stop() 功能,但它们可能没有其他的共同点。

抽象类可以实现接口

尽管抽象类不能被直接实例化,但它们可以实现接口中的方法,而不一定要求子类必须重新实现。这种做法适合为接口提供部分实现,子类可以选择使用或覆盖它们。

interface Walkable {void walk();
}abstract class Animal implements Walkable {@Overridepublic void walk() {System.out.println("Animal is walking.");}// 抽象类中可以有自己的抽象方法public abstract void makeSound();
}

在这个例子中,抽象类 Animal 实现了 Walkable 接口中的 walk() 方法,而子类可以继承这个实现或进行自定义。

接口中的常量其实是 public static final

在接口中定义的字段默认是 public static final,即它们都是常量,必须在声明时初始化,且不能修改。即使你没有显式声明这些修饰符,编译器也会自动加上。

interface MyConstants {// 实际上等同于:public static final int MAX_VALUE = 100int MAX_VALUE = 100; 
}

这意味着接口中的所有字段都是全局常量,并且只能用于共享常量的场景。

标记接口(Marker Interface)

Java 中有一种特殊的接口叫做标记接口(Marker Interface),它没有任何方法,作用仅仅是标记某个类具有某种特性。比如 java.io.Serializable,实现了这个接口的类可以被序列化。

interface MarkerInterface {// 没有方法,仅用于标记类具有某种属性
}class MyClass implements MarkerInterface {// 这个类被标记为拥有 MarkerInterface 的属性
}

标记接口本质上是一种元数据,用于表示类的某些行为或特性。这种设计理念后来被注解(Annotations)部分取代。

接口可以扩展多个接口

一个接口可以继承多个接口,这让 Java 实现了某种形式的“多继承”,但它不同于类的多继承,类的多继承在 Java 中是被禁止的。这种机制允许你通过继承多个接口来组合各种行为。

interface Eater {void eat();
}interface Sleeper {void sleep();
}interface Animal extends Eater, Sleeper {void makeSound();
}class Dog implements Animal {@Overridepublic void eat() {System.out.println("Dog is eating.");}@Overridepublic void sleep() {System.out.println("Dog is sleeping.");}@Overridepublic void makeSound() {System.out.println("Dog says: Woof!");}
}

Dog 类通过实现 Animal 接口,间接地获得了 EaterSleeper 接口中的方法。这种设计使得代码更具扩展性。

接口中的方法可以有多个默认实现来源

在 Java 8 引入了默认方法后,一个类可以从多个接口继承默认方法。如果这些接口中定义了相同的方法名,类必须手动解决冲突。这种情况在多重继承的情况下常见。

interface InterfaceA {default void show() {System.out.println("InterfaceA");}
}interface InterfaceB {default void show() {System.out.println("InterfaceB");}
}class MyClass implements InterfaceA, InterfaceB {@Overridepublic void show() {InterfaceA.super.show();  // 选择调用 InterfaceA 的 show()}
}

在这种情况下,你必须明确指明调用哪个接口的默认实现。通过 InterfaceA.super.show() 可以解决冲突。

本期小知识

在 Java 8 之后,接口中可以定义默认方法(default methods)和静态方法。这是接口功能的重要扩展,因为传统的接口不能包含实现。

默认方法:允许在接口中定义方法的默认实现,不强制要求实现类去实现它们。这在维护接口的向后兼容性上起到了很大作用。

interface Vehicle {default void start() {System.out.println("Starting the vehicle");}
}

静态方法:接口中的静态方法只能通过接口名称调用,不能被子类继承或覆盖。

interface Vehicle {static void checkEngine() {System.out.println("Engine checked");}
}

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

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

相关文章

C语言图形编程:构建视觉效果与应用

引言 在计算机科学的领域中,C语言凭借其简洁、高效以及对底层硬件的强大控制能力,一直是系统级编程的首选语言之一。尽管近年来出现了许多高级语言,但C语言仍然在多个领域占据着重要地位,特别是在图形编程方面。本文将深入探讨如…

粒子向上持续瀑布动画效果(直接粘贴到记事本改html即可)

代码&#xff1a; 根据个人喜好修改即可 <!DOCTYPE html> <html lang"zh"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>宽粒子向上…

MOSFET是什么,终于有了一点点感知

目录 MOSFET是什么&#xff1f;FETMOS MOSFET和功率MOSFETMOSFET功率MOSFET MOSFET是什么&#xff1f; 英文是metal-oxide-semiconductor-field-effect-transistor&#xff0c;金属氧化物半导体场效应晶体管。 可以分开来看一下&#xff0c;MOS和FET FET 其中&#xff0c;FE…

图片类型转化---模拟某wps

文件上传功能的深入探讨 文件上传是Web应用程序中常见的功能&#xff0c;它允许用户将本地文件通过Web界面发送到服务器。在Flask中&#xff0c;这通常是通过处理表单数据来实现的。表单必须设置enctype为multipart/form-data&#xff0c;这样浏览器才能将文件作为多部分消息发…

Linux常用命令(部分学习待继续补充)

pwd print working directory 打印当前的工作目录 / 根目录 ls list 列出当前目录下的所有文件 ls / ls -h(human) ls -l(long) cd change directory 更改目录 cd … 回到上一级目录 ls list ls -l 会列出文件的详细信息 第一个字符是-表示普通文件 d表示是一个目录 rwx read …

keil 下载安装 保姆级教程

一.前言 最近被安排开发一个单片机的项目&#xff0c;回头想了一下&#xff0c;自己上次弄单片机的时候&#xff0c;还都是在大学期间&#xff0c;到现在也有三四年没有碰过了&#xff0c;大部分的知识点都忘了&#xff0c;所以又重新的把以前的笔记和资料&#xff0c;拿出来温…

NXP实战笔记(十六):NXP 32K3xx系列单片机有关OTA升级的思考

目录 1、概述 2、参考资料 3、思考点1&#xff1a;需不需要传统BootLoader&#xff1f; 3.1、无需传统BootLoader 3.2、有传统BootLoader 4、OTA升级之后是否立即实施切换 5、兼容编程会话 6、APP内部集成34、36、37服务 7、Flash放置问题 1、概述 NXP的S32K3系列单片机…

初写MySQL四张表:(4/4)

进度条很喜人&#xff0c;你是否已经修炼到这一步了呢&#xff1f; 初写MySQL四张表:(1/4)-CSDN博客 初写MySQL四张表:(2/4)_数据库表样例-CSDN博客 初写MySQL四张表:(3/4)-CSDN博客 若现在你已经有了前面的基础&#xff0c;那就正式开始吧。 四张表&#xff1a; 这次在实现…

不同编程语言的互相调用

C语言与Python 步骤&#xff1a; 编写C代码 (hello_c.c): #include <stdio.h>void printHello(const char *name) {printf("Hello, %s!\n", name); }编译C代码为共享库: gcc -shared -o hello_c.so hello_c.c编写Python代码 (hello_c_py.py): import ctypes# …

CocosCreator 3.x 实现角色移动与加载时动态屏幕边缘检测

效果 思路 通过cc.view全局单例 View 对象获取屏幕尺寸加载时根据屏幕尺寸动态计算上下左右边缘 代码实现 import { _decorator, Component, EventTouch, Input, input, Node, view } from cc; const { ccclass, property } _decorator;/*** 玩家控制脚本*/ ccclass(Player…

探索AI编程新时代:GitHub Copilot如何重塑开发者工作效率

在当今技术瞬息万变的时代&#xff0c;软件开发者们每天都在努力寻找更高效的编程方法。面对繁忙的工作日程和不断增加的项目压力&#xff0c;如何在编码过程中大幅提升效率成为了一个备受关注的话题。在众多工具中&#xff0c;GitHub Copilot以其强大的AI驱动能力脱颖而出&…

二叉树的层序遍历(含八道leetcode相关题目)

文章目录 二叉树层序遍历模板102. 二叉树的层序遍历107. 二叉树的层序遍历 II199. 二叉树的右视图637. 二叉树的层平均值515. 在每个树行中找最大值429. N 叉树的层序遍历116. 填充每个节点的下一个右侧节点指针117. 填充每个节点的下一个右侧节点指针 II 二叉树层序遍历模板 …

基于Java springboot+mybatis 网上商城系统

基于Java springbootmybatis 网上商城系统 一、系统介绍二、功能展示1.主页(客户)2.登陆&#xff08;客户&#xff09;3.注册&#xff08;客户&#xff09;4.购物车(客户)5.我的订单&#xff08;客户&#xff09;6.用户管理&#xff08;管理员&#xff09;7.分类管理&#xff0…

Cisco 基础网络汇总

⭕个人主页 可惜已不在 ⭕可以分享给身边有需要的人 ⭕有用的话就留下一个三连吧 目录 前言: 一.网络及网络设备认识 二. 二层网络 三. 生成树、端口 四. 三层网络 五.访问控制 六.NAT 七.DHCP 八.PPP 九.帧中继 十.热备份 十一.综合实验 十二.WLAN 十三.Cisco P…

华为全联接大会HUAWEI Connect 2024印象(一):OpenEuler

因为和华为有课程合作&#xff0c;此次应邀参加了华为全联接大会 &#xff08;HUAWEI Connect 2024&#xff09;&#xff0c;分几次分享一下自己的见闻。 HUAWEI Connect 2024的规模很大&#xff0c;不过主要面向的应该是企业市场&#xff0c;我比较关注的嵌入式系统的内容很少…

OpenAI o1-preview和o1-mini现已在 GitHub Copilot和GitHub Models中提供

微软 GitHub 今天宣布在 GitHub Copilot和 Models 中提供两个新的 Open AI 模型&#xff1a;o1-preview 和 o1-mini。OpenAI 推出了新的 o1 系列 人工智能模型&#xff0c;旨在花更多时间思考后再做出反应。与以前的 OpenAI 模型相比&#xff0c;这些模型能在科学、编码和数学领…

C++速通LeetCode中等第18题-删除链表的倒数第N个结点(最简单含注释)

绝妙&#xff01;快慢指针法,快指针先走n步&#xff08;复杂度O(n),O(1))&#xff1a; /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode() : val(0), next(nullptr) {}* ListNode(int x) : val(x), next(n…

使命召唤游戏助手系统小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;玩家管理&#xff0c;游戏分类管理&#xff0c;道具种类管理&#xff0c;游戏道具处管理&#xff0c;战绩信息管理&#xff0c;水平评估管理&#xff0c;系统管理 微信端账号功能包括&#xff1a;系统…

Spring源码-从源码层面讲解声明式事务的运行流程

TxTest开始执行事务方法: public class TxTest {public static void main(String[] args) throws SQLException {System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY,"d:\\code");ApplicationContext context new ClassPathXmlApplicationContext(&…

如何将生物序列tokenization为token?

原理讲解 tokenization是自然语言处理领域非常成熟的一项技术&#xff0c;tokenization就是把我们研究的语言转换成计算机能够识别的数字——token。 在生物领域&#xff0c;如何把核苷酸或氨基酸序列tokenization成token呢&#xff1f; 我们可以使用k-mer技术&#xff1a; k-m…