几周前,我们详细研究了默认方法 -Java 8中引入的一项功能,该功能允许为接口方法提供实现,即方法主体,从而定义接口中的行为。 引入此功能是为了实现接口演进 。

在JDK的上下文中,这意味着在不破坏所有代码的情况下向接口添加新方法。 但是,尽管Java本身非常致力于保持向后兼容性,但其他项目并不一定要做到这一点。 如果他们愿意,他们可以以让客户更改代码为代价来开发接口。

在Java 8之前,这经常涉及客户端编译错误,因此可以避免更改,否则客户端必须一次性迁移。 使用默认方法,接口演变可以成为一个无错误的过程,在此过程中,客户端可以在版本之间留出时间来逐步更新代码。 这大大增加了开发接口的可行性,并使其成为常规的库开发工具。

让我们看一下如何添加,替换和删除接口方法。 未来的文章将探讨替换整个接口的方法。

总览

该帖子首先定义了一些术语,然后介绍了添加,替换和删除接口方法的方法。 它是从更改库中界面的开发人员的角度编写的。

我觉得该主题不需要示例,因此我没有编写任何示例。 如果您不同意并希望看到一些内容,请发表评论,并且-在时间允许的情况下-我会写一些。

术语

接口具有实现调用者 。 两者都可以存在于库中,在这种情况下,它们都称为internal ,或者在客户端代码中称为external 。 这总共增加了四种使用界面的类别。

根据界面的发展方式和存在的用途,必须采用不同的模式。 当然,如果既不存在外部实现也不存在外部调用者,则这些都不是必需的,因此本文的其余部分假定这些情况中至少有一种确实存在。

接口演变–方法

因此,让我们看看如何在不破坏客户端代码的情况下添加,替换或删除接口方法。

通常可以通过执行以下过程来实现:

新版本

该库的新版本已发布,其中界面定义是过渡性的,并结合了旧的和新的所需轮廓。 默认方法可确保所有外部实现和调用仍然有效,并且在更新时不会出现编译错误。

过渡

然后,客户就有时间从旧大纲过渡到新大纲。 同样,默认方法可确保适应的外部实现和调用有效,并且可以进行更改而不会编译错误。

新版本

在新版本中,该库删除了旧轮廓的残差。 鉴于客户端明智地利用了自己的时间并进行了必要的更改,因此发布新版本不会导致编译错误。

这个过程使客户能够按自己的时间表平稳地更新代码,这使得接口的发展比以前更加可行。

Johanna Pung在CC-BY-SA 3.0下为Wikimedia Deutschland 发布 。

遵循以下详细步骤时,请确保检查何时更新了内部和外部实现以及何时允许内部和外部调用者使用所涉及的方法。 确保在您自己的代码中遵循此过程,并为您的客户正确记录下来,以便他们知道何时执行操作。 Javadoc标签@Deprecated@apiNote是实现此目的的好方法。

通常,不必按该顺序执行过渡内的步骤。 如果是,则明确指出。

如果您向客户提供可以在其界面实现上运行的测试,则这些步骤中包含测试。

仅当存在外部接口实现时才需要此过程。 由于该方法是新方法,因此当然尚未调用,因此可以忽略这种情况。 区分是否可以提供合理的默认实现是有意义的。

存在合理的默认实现

新版本
  • 为新方法定义测试
  • 使用默认实现(通过测试)添加方法
  • 内部呼叫者可以使用该方法
  • 内部实现可以在必要时覆盖该方法
过渡
  • 外部呼叫者可以使用该方法
  • 外部实现可以在必要时覆盖该方法

无需执行任何操作,也不需要任何新版本。 这就是Java 8中添加的许多新的默认方法所发生的事情。

不存在合理的默认实现

新版本
  • 定义新方法的测试; 这些必须接受UnupportedOperationExceptions
  • 添加方法:
    • 包括一个引发UnupportedOperationException的默认实现(通过测试)
    • @apiNote注释文档,默认实现将最终被删除
  • 在所有内部实现中覆盖该方法
过渡

必须按该顺序执行以下步骤:

  • 外部实现必须重写该方法
  • 外部呼叫者可以使用该方法
新版本
  • 测试不再接受UnupportedOperationExceptions
  • 使方法抽象:
    • 删除默认实现
    • 删除@apiNote注释
  • 内部呼叫者可以使用该方法

勉强一致的默认实现允许外部实现逐渐更新。 请注意,在实际在内部或外部调用新方法之前,将更新所有实现。 因此,永远不会发生UnupportedOperationException。

更换

在这种情况下,一种方法将被另一种方法替代。 这包括方法更改其签名(例如,其名称或参数数量)的情况,在这种情况下,新版本可以看作是替换旧版本。

当存在外部实现或外部调用者时,必须应用此模式。 仅在两种方法在功能上等效时才起作用。 否则,就是添加一个功能并删除另一个功能的情况。

新版本
  • 为新方法定义测试
  • 添加新方法:
    • 包括调用旧方法的默认实现
    • @apiNote注释文档,默认实现将最终被删除
  • 弃用旧方法:
    • 包括调用新方法的默认实现(旨在进行循环调用;如果存在默认实现,则可以保留)
    • @apiNote注释文档,默认实现将最终被删除
    • @Deprecation评论文档说明将使用新方法
  • 内部实现会覆盖新方法,而不是旧方法
  • 内部调用者使用新方法代替旧方法
过渡
  • 外部实现会覆盖新方法,而不是旧方法
  • 外部呼叫者使用新方法代替旧方法
新版本
  • 使新方法抽象:

    • 删除默认实现
    • 删除@apiNote注释
  • 删除旧方法

尽管循环调用看起来很有趣,但它们确保实现哪种方法都无关紧要。 但是,由于这两种变体都有默认实现,因此,如果两种实现均未实现,则编译器不会产生错误。 不幸的是,这会产生无限循环,因此请确保将其指出给客户。 如果您为他们的实现提供测试,或者他们编写了自己的实现,则他们会立即意识到这一点。

去掉

删除方法时,根据是否存在外部实现,可以应用不同的模式。

存在外部实现

新版本
  • 方法的测试必须接受UnupportedOperationExceptions
  • 弃用该方法:
    • 包括一个引发UnupportedOperationException的默认实现(通过更新的测试)
    • @Deprecation注释文档表明该方法最终将被删除
    • @apiNote注释文档说明默认实现仅存在于逐步淘汰方法中
  • 内部呼叫者停止使用该方法
过渡

必须按该顺序执行以下步骤:

  • 外部呼叫者停止使用该方法
  • 该方法的外部实现已删除
新版本
  • 删除方法

请注意,只有在不存在对该方法的更多调用之后,才删除内部和外部实现。 因此,永远不会发生UnupportedOperationException。

外部实现不存在

在这种情况下,定期弃用就足够了。 仅出于完整性考虑而列出了这种情况。

新版本
  • @Depreated弃用该方法
  • 内部呼叫者停止使用该方法
过渡
  • 外部呼叫者停止呼叫方法
新版本
  • 删除方法

反射

我们已经看到了如何通过添加,替换和删除方法来实现界面演化:新的界面版本结合了旧轮廓和新轮廓,客户端从前者过渡到后者,而最终版本则消除了旧轮廓的残留。 所涉及方法的默认实现确保客户端代码的旧版本和新版本都能正确编译和运行。

翻译自: https://www.javacodegeeks.com/2015/03/interface-evolution-with-default-methods-part-i-methods.html

使用默认方法的界面演变–第一部分:方法相关推荐

  1. viewpager默认界面_使用默认方法的界面演变–第一部分:方法

    viewpager默认界面 几周前,我们详细研究了默认方法 -Java 8中引入的一项功能,该功能允许为接口方法提供实现,即方法主体,从而定义接口中的行为. 引入此功能是为了实现接口演进 . 在JDK ...

  2. java执行完main就结束了吗_为什么main方法中执行完第一个方法完之后,后面的代码都不执行了?...

    package chap05; public class StringFindTest { public static void testFind(String str, String substr) ...

  3. pdf压缩方法总结pdf如何减少体积方法

    现实生活中,我们碰到的pdf扫描版文件十分庞大,基本都在100M或者几百兆有没有方法可以减少体积而又不损失清晰度方法呢,方法还是有的,只不过需要自己总结探索,目前就笔者方法总结一下: 第一种方法:使用 ...

  4. vue项目中:PC端导出csv或excel数据表方法及其移动端导出表格方法

    需求是在前端导出人员明细表,后端只给提供json格式的数据,函数方法如下: 一:第一种方法:(不可移动端导出) // 导出明细csv格式(纯前端导出)getExport() {// this.getD ...

  5. VC开发多语言界面支持的简单方法

    VC开发多语言界面支持的简单方法 作者:成晓旭 (需要完整源代码请留言) 最近在做一个小程序,要求实现对多语言界面显示支持功能,并且,界面显示内容用户能够自己设置. 初步设计用INI文件来配置显示内容 ...

  6. 【Vegas原创】安装rhel6.2,不能进图形化界面的终极解决方法

    安装的时候,千万不要一路下一步,you should know,linux不是windows那么的傻瓜. 方法一: 在倒数最后一步,选择Desktop,而千万不要下一步,默认选择Basic Serve ...

  7. 【Java2】一维数组,家庭收支界面,/属性和方法,方法重载,变量分类,可变参数,包

    文章目录 1.一维数组:int[ ] a = { } 1.1 数组的内存分析(静态):数组名=首地址 1.2 数组的内存分析(动态):元素默认值 1.3 数组相关算法: 1.3.1 找最值:array ...

  8. Linux QT5.12 一种整体界面字体设置的方法及设置PlainTextEdit组件的字体大小方法

    1.在Linux QT5.12开发界面时,经常会涉及到界面字体大小的设置,默认字体一般比较小,解决方法如下: 在main函数中添加代码: //============================= ...

  9. Qt5.9一个简单的多线程实例(类QThread)(第一种方法)

    Qt开启多线程,主要用到类QThread.有两种方法,第一种用一个类继承QThread,然后重新改写虚函数run().当要开启新线程时,只需要实例该类,然后调用函数start(),就可以开启一条多线程 ...

最新文章

  1. 食品行业特点及SAP解决方案探讨
  2. 怎么修改CSDN上传图片水印的字体大小?(去水印)
  3. 调优您的 LAMP 应用程序的 5 种简单方法
  4. Python之字典类型数据常见操作及排序
  5. Python3 三步爬楼梯问题
  6. python魔术方法abstract_python学习之面向对象高级特性和魔术方法
  7. strassen算法java_使用java写的矩阵乘法实例(Strassen算法)_Java_软件编程
  8. 中国内容推荐引擎市场趋势报告、技术动态创新及市场预测
  9. linux vi编辑撤销,vi撤销命令(u和U),撤销上一次的操作
  10. m2接口和nvme协议接口_怎么看笔记本的主板是支持加装m2接口和m2协议NVME接口的固态硬盘?两者有什么区别?...
  11. 电商项目5:商品模块
  12. ls 命令显示的total是什么意思
  13. 农夫山泉又上热搜,虚假宣传、拒不认错让网友反感至极!
  14. Xmanager的xbrowser登陆图形界面
  15. 关于Google您的连接不是私密连接问题的解决方法 (Chrome 地址栏 Google 搜索错误处理 隐私设置错误)
  16. 如何UNI-APP中使用iconfont彩色图标
  17. Echarts学习总结(一)-----柱状图
  18. ORB-SLAM2的安装及试运行
  19. Java计算机毕业设计舒旅程旅游景点预订网站源码+系统+数据库+lw文档
  20. am服务器查找信息,am服务器

热门文章

  1. 使用ueditor实现多图片上传案例——截取字符串层Util(SubString_text)
  2. 当当网新用户注册界面——界面源码
  3. 2017蓝桥杯省赛---java---B---7(日期问题)
  4. mysql加索引快很多
  5. mysql根据注释搜索表
  6. 转: 记录centos7 安装erlang22.3和rabbitMQ
  7. 程序编码(机器级代码+汇编代码+C代码+反汇编)
  8. Spring boot (5):Spring data jpa 的使用
  9. java延时执行_Java谓词的延迟执行
  10. ibm liberty_使用Eclipse和Open Liberty的Java EE 8上的Java 9