Java接口中的默认方法(Default Methods)

前言

在Java 8发布之后,接口的功能得到了显著增强,其中最引人注目的特性之一就是默认方法。默认方法允许接口提供带有实现的方法,这不仅不会破坏现有代码的兼容性,还能为所有实现了该接口的类直接提供新功能。

默认方法的基础知识

接口与抽象方法回顾

在Java中,接口是一种特殊的引用类型,它定义了一组行为规范,但不提供具体实现。任何实现了该接口的类都必须提供这些行为的具体实现。例如:

public interface MyInterface {void doSomething();
}

在这个例子中,doSomething是一个抽象方法,任何实现了MyInterface接口的类都必须提供这个方法的具体实现。

默认方法的引入

随着Java的发展,有时候我们想要给已有的接口添加新的功能,但又不想破坏现有的实现类。这时候,默认方法就派上用场了。默认方法允许我们在接口中定义具有默认实现的方法,这样即使没有显式覆盖,也能使用这些方法。默认方法使用default关键字来声明:

public interface MyInterface {// 抽象方法void doSomething();// 默认方法default void doAnotherThing() {System.out.println("This is a default method.");}
}

现在,任何实现了MyInterface接口的类都可以调用doAnotherThing()方法,而不需要额外的实现。

默认方法的作用

  • 向后兼容性:可以在不改变现有代码的情况下为接口添加新方法。
  • 减少重复代码:可以将公共逻辑放在接口级别,避免每个实现类都写相同的代码。
  • 简化API设计:使得接口更加灵活,可以根据需要选择是否覆盖默认方法。

使用默认方法

创建并实现包含默认方法的接口

首先,让我们创建一个包含默认方法的接口,并展示如何在实现类中使用它。

// 定义接口
public interface MyInterface {void doSomething();default void doAnotherThing() {System.out.println("This is a default method from MyInterface.");}// 另一个默认方法default void greet() {System.out.println("Hello from MyInterface!");}
}// 实现接口的类
public class MyClass implements MyInterface {@Overridepublic void doSomething() {System.out.println("Doing something in MyClass.");}// 覆盖默认方法@Overridepublic void greet() {System.out.println("Greetings from MyClass!");}// 可以不覆盖 doAnotherThing 方法,因为已经有了默认实现
}

调用默认方法

接下来,我们将创建MyClass的一个实例,并调用其方法来看看结果。

public class Main {public static void main(String[] args) {MyInterface myInstance = new MyClass();myInstance.doSomething();      // 输出: Doing something in MyClass.myInstance.doAnotherThing();   // 输出: This is a default method from MyInterface.myInstance.greet();            // 输出: Greetings from MyClass!}
}

如你所见,doAnotherThing方法直接使用了接口提供的默认实现,而greet方法则被MyClass类覆写了,因此输出的是覆写后的版本。

解决多重继承冲突

当一个类实现了多个接口时,如果这些接口中有同名的默认方法,就会出现冲突。此时,你需要在你的类中明确指定要使用哪个接口的默认方法,或者提供自己的实现。

interface InterfaceA {default void hello() {System.out.println("Hello from InterfaceA");}
}interface InterfaceB {default void hello() {System.out.println("Hello from InterfaceB");}
}class MyClass implements InterfaceA, InterfaceB {// 解决冲突,选择其中一个接口的方法或提供自己的实现@Overridepublic void hello() {InterfaceA.super.hello(); // 显式调用InterfaceA的hello方法InterfaceB.super.hello(); // 显式调用InterfaceB的hello方法}
}

应用案例分析

字典服务接口的实际应用

这是若依框架中字典服务接口DictService,它提供了根据字典类型和值或标签获取相关信息的功能。这里我们简单介绍下如何利用默认方法来简化接口的设计。

import org.apache.commons.lang3.StringUtils;public interface DictService {/*** 根据字典类型和字典值获取字典标签,默认使用分隔符。*/default String getDictLabel(String dictType, String dictValue) {return getDictLabel(dictType, dictValue, StringUtils.SEPARATOR);}/*** 根据字典类型和字典标签获取字典值,默认使用分隔符。*/default String getDictValue(String dictType, String dictLabel) {return getDictValue(dictType, dictLabel, StringUtils.SEPARATOR);}/*** 根据字典类型和字典值获取字典标签,指定分隔符。*/String getDictLabel(String dictType, String dictValue, String separator);/*** 根据字典类型和字典标签获取字典值,指定分隔符。*/String getDictValue(String dictType, String dictLabel, String separator);
}

在这个例子中,getDictLabelgetDictValue两个默认方法简化了调用者提供的参数数量,同时保持了灵活性,因为底层实现仍然支持自定义分隔符。这减少了调用者的负担,同时也确保了代码的一致性和可维护性。

实现DictService接口

为了使上述接口更有意义,我们可以创建一个简单的实现类,演示如何使用默认方法:

public class SimpleDictServiceImpl implements DictService {private final Map<String, Map<String, String>> dictionary;public SimpleDictServiceImpl(Map<String, Map<String, String>> dictionary) {this.dictionary = dictionary;}@Overridepublic String getDictLabel(String dictType, String dictValue, String separator) {if (dictionary.containsKey(dictType)) {for (Map.Entry<String, String> entry : dictionary.get(dictType).entrySet()) {if (entry.getValue().equals(dictValue)) {return entry.getKey();}}}return null; // 或者抛出异常,取决于业务需求}@Overridepublic String getDictValue(String dictType, String dictLabel, String separator) {if (dictionary.containsKey(dictType)) {return dictionary.get(dictType).get(dictLabel);}return null; // 或者抛出异常,取决于业务需求}
}

在此实现中,我们假设有一个内部的字典数据结构,用来存储不同类型的字典条目。SimpleDictServiceImpl类提供了具体的实现,同时利用了DictService接口中定义的默认方法,简化了对外部用户的API。

默认方法的优点

  1. 向后兼容性:可以在不破坏现有代码的情况下为接口添加新功能。
  2. 方法复用:提供了一种在接口层面共享公共实现的方式,避免了重复代码。
  3. 减少样板代码:对于一些常见的操作或辅助功能,可以将其直接放在接口中作为默认方法,从而减少每个实现类中相似的样板代码。
  4. 提升灵活性:实现类可以选择是否覆盖默认方法,增强了设计上的灵活性。
  5. 简化API设计:可以通过默认方法提供简洁的API,隐藏复杂的实现细节。

结论

默认方法是Java 8引入的一个重要特性,它增强了接口的功能,使接口更加灵活且易于扩展。通过理解并正确使用默认方法,开发者可以编写更简洁、更可维护的代码。

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

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

相关文章

GAN对抗生成网络(二)——算法及Python实现

1 算法步骤 上一篇提到的GAN的最优化问题是&#xff0c;本文记录如何求解这一问题。 首先为了表示方便&#xff0c;记&#xff0c;这里让最大的可视作常量。 第一步&#xff0c;给定初始的&#xff0c;使用梯度上升找到 ,最大化。关于梯度下降&#xff0c;可以参考笔者另一篇…

[读书日志]从零开始学习Chisel 第二篇:Scala的变量与函数(敏捷硬件开发语言Chisel与数字系统设计)

第一篇https://blog.csdn.net/m0_74021449/article/details/144887921 2.2 Scala的变量及函数 2.2.1变量定义与基本类型 变量声明 变量首次定义必须使用关键字var或者val&#xff0c;二者的区别是val修饰的变量禁止被重新赋值&#xff0c;它是一个只读的变量。首次定义变量时…

Spring Boot - 日志功能深度解析与实践指南

文章目录 概述1. Spring Boot 日志功能概述2. 默认日志框架&#xff1a;LogbackLogback 的核心组件Logback 的配置文件 3. 日志级别及其配置配置日志级别3.1 配置文件3.2 环境变量3.3 命令行参数 4. 日志格式自定义自定义日志格式 5. 日志文件输出6. 日志归档与清理7. 自定义日…

NVIDIA DLI课程《NVIDIA NIM入门》——学习笔记

先看老师给的资料&#xff1a; NVIDIA NIM是 NVIDIA AI Enterprise 的一部分&#xff0c;是一套易于使用的预构建容器工具&#xff0c;目的是帮助企业客户在云、数据中心和工作站上安全、可靠地部署高性能的 AI 模型推理。这些预构建的容器支持从开源社区模型到 NVIDIA AI 基础…

JOIN 和 OUTER JOIN,SQL中常见的连接方式

1. INNER JOIN&#xff08;简称 JOIN&#xff09; INNER JOIN 是 SQL 中最常用的一种连接方式&#xff0c;默认的 JOIN 就是 INNER JOIN。它返回两个表中满足连接条件的匹配记录。 作用&#xff1a;返回两个表中所有满足 ON 条件的记录。特性&#xff1a;如果表中的某些行在连…

【HF设计模式】05-单例模式

声明&#xff1a;仅为个人学习总结&#xff0c;还请批判性查看&#xff0c;如有不同观点&#xff0c;欢迎交流。 摘要 《Head First设计模式》第5章笔记&#xff1a;结合示例应用和代码&#xff0c;介绍单例模式&#xff0c;包括遇到的问题、采用的解决方案、以及达到的效果。…

【FlutterDart】页面切换 PageView PageController(9 /100)

上效果&#xff1a; 有些不能理解官方例子里的动画为什么没有效果&#xff0c;有可能是我写法不对 后续如果有动画效果修复了&#xff0c;再更新这篇&#xff0c;没有动画效果&#xff0c;总觉得感受的丝滑效果差了很多 上代码&#xff1a; import package:flutter/material.…

Electron快速入门——跨平台桌面端应用开发框架

个人简介 &#x1f440;个人主页&#xff1a; 前端杂货铺 &#x1f64b;‍♂️学习方向&#xff1a; 主攻前端方向&#xff0c;正逐渐往全干发展 &#x1f4c3;个人状态&#xff1a; 研发工程师&#xff0c;现效力于中国工业软件事业 &#x1f680;人生格言&#xff1a; 积跬步…

Android NDK开发实战之环境搭建篇(so库,Gemini ai)

文章流程 音视频安卓开发首先涉及到ffmpeg编译打包动态库&#xff0c;先了解动态库之间的cpu架构差异性。然后再搭建可运行的Android 环境。 So库适配 ⽇常开发我们经常会使⽤到第三库&#xff0c;涉及到底层的语⾳&#xff0c;视频等都需要添加so库。⽽so库的体积⼀般来说 ⾮…

【Java回顾】Day2 正则表达式----异常处理

参考资料&#xff1a;菜鸟教程 https://www.runoob.com/java/java-exceptions.html 正则表达式 有一部分没看完 介绍 字符串的模式搜索、编辑或处理文本java.util.regex包&#xff0c;包含了pattern和mathcer类&#xff0c;用于处理正则表达式的匹配操作。 捕获组 把多个字符…

Unity性能优化总结

目录 前言 移动端常见性能优化指标​编辑 包体大小优化 FPS CPU占用率 GPU占用率 内存 发热和耗电量 流量优化 前言 终于有时间了&#xff0c;我将在最近两个项目中进行优化的一些经验进行归纳总结以飨读者。因为我习惯用思维导图&#xff0c;所以归纳的内容主要以图来…

FTP上传下传、SFTP上传下传、进度监控、断点续传、连接池封装JAVA一网打尽(二)FTP高级篇【2/5】

一、摘要&#xff08;本系列汇总说明&#xff09; - 总纲 FTP、SFTP上传下传、进度监控、断点续传、连接池封装JAVA一网打尽&#xff08;一&#xff09;FTP、SFTP上传下传、进度监控、断点续传、连接池封装JAVA一网打尽&#xff08;二&#xff09;FTP、SFTP上传下传、进度监控…

北京航空航天大学惊现技术商业“宫斗剧”!背后隐藏的内幕遭曝光!

北京航空航天大学&#xff08;以下称北航&#xff09;与源亿&#xff08;北京&#xff09;网络科技有限公司&#xff08;以下称源亿&#xff09;的派驻的员工恶意串通&#xff0c;指定北京蚂蚁非标科技有限公司&#xff08;以下称蚂蚁公司&#xff09;挖走源亿公司在现场派驻的…

transfomer深度学习实战水果识别

本文采用RT-DETR作为核心算法框架&#xff0c;结合PyQt5构建用户界面&#xff0c;使用Python3进行开发。RT-DETR以其高效的实时检测能力&#xff0c;在多个目标检测任务中展现出卓越性能。本研究针对水果数据集进行训练和优化&#xff0c;该数据集包含丰富的水果图像样本&#…

Python世界:人生苦短,我用Python

Python世界&#xff1a;人生苦短&#xff0c;我用Python 前言Python优势Python缺点 前言 几句话说清&#xff0c;我们为啥要用Python&#xff1f; Python设计之初心&#xff0c;是为了解决编程门槛&#xff0c;让大家更聚焦业务实现&#xff0c;而非编程细节。当前人工智能火…

TensorFlow深度学习实战(3)——深度学习中常用激活函数详解

TensorFlow深度学习实战&#xff08;3&#xff09;——深度学习中常用激活函数详解 0. 前言1. 引入激活函数1.1 感知器1.2 多层感知器1.3 训练感知器存在的问题 2. 激活函数3. 常见激活函数3.1 sigmoid3.2 tanh3.3 ReLU3.4 ELU和Leaky ReLU 小结系列链接 0. 前言 使用激活函数…

Linux vi/vim 编辑器:功能强大的文本处理工具

Linux vi/vim 编辑器&#xff1a;功能强大的文本处理工具 引言 Linux 系统中的 vi/vim 是一种功能强大的文本编辑器&#xff0c;它广泛应用于程序员、系统管理员和其他需要处理文本文件的用户群体中。vi 是 visual interface 的缩写&#xff0c;而 vim 则是 vi improved 的缩…

C#设计模式(行为型模式):状态模式

C#设计模式&#xff1a;状态模式 在软件开发中&#xff0c;我们经常会遇到对象的行为取决于其状态的情况。例如&#xff0c;一个订单对象可能处于“待支付”、“已支付”、“已发货”等不同状态&#xff0c;而每个状态下订单的行为&#xff08;例如是否可以支付、是否可以发货…

数据结构C语言描述9(图文结合)--二叉树和特殊书的概念,二叉树“最傻瓜式创建”与前中后序的“递归”与“非递归遍历”

前言 这个专栏将会用纯C实现常用的数据结构和简单的算法&#xff1b;有C基础即可跟着学习&#xff0c;代码均可运行&#xff1b;准备考研的也可跟着写&#xff0c;个人感觉&#xff0c;如果时间充裕&#xff0c;手写一遍比看书、刷题管用很多&#xff0c;这也是本人采用纯C语言…

Leetcode打卡:设计一个ATM机器

执行结果&#xff1a;通过 题目 2241 设计一个ATM机器 一个 ATM 机器&#xff0c;存有 5 种面值的钞票&#xff1a;20 &#xff0c;50 &#xff0c;100 &#xff0c;200 和 500 美元。初始时&#xff0c;ATM 机是空的。用户可以用它存或者取任意数目的钱。 取款时&#xff0c…