Effective Java笔记(21)为后代设计接口

《Effective Java》第21条:为后代设计接口 这是缺省方法的好处之一,但是,给现有的接口添加新方法还是充满风险的,因为实现该接口的类并不知道接口中已经增加了一个缺省方法,也没有经过实现类的许可,虽然这样可能不会导致什么问题,但是是一个隐患。5. 为了避免发生这种异常,维护人员必须要覆盖默认的 removeIf 实现,以及一些类似于 removeIf 的其他方法,以便在调用缺省实现之前执行必要的同步。默认方法是 “通用” 的,但集合的实现是多样的 —— 有些实现有特殊逻辑(比如同步、并发控制、自定义迭代规则),默认方法没法兼顾所有变体。 阅读详情

        在Java 8发行之前,如果不破坏现有的实现,是不可能给接口添加方法的。如果给某个接口添加了一个新的方法,一般来说,现有的实现中是没有这个方法的,因此就会导致编译错误。在Java8中,增加了缺省方法( default method)构造,目的就是允许给现有的接口添加方法。但是给现有接口添加新方法还是充满风险的。

        缺省方法的声明中包括一个缺省实现( default implementation),这是给实现了该接口但没有实现默认方法的所有类使用的。虽然Java中增加了缺省方法之后,可以给现有接口添加方法了,但是并不能确保这些方法在之前存在的实现中都能良好运行。因为这些默认的方法是被“注入”到现有实现中的,它们的实现者并不知道,也没有许可。在Java8之前,编写这些实现时,是默认它们的接口永远不需要任何新方法的。

        Java 8在核心集合接口中增加了许多新的缺省方法,主要是为了便于使用lambda 。Java类库的缺省方法是高品质的通用实现,它们在大多数情况下都能正常使用。但是,并非每一个可能的实现的所有变体,始终都可以编写出一个缺省方法。

        比如,以removeIf方法为例,它在Java 8中被添加到了Collection接口。这个方法用来移除所有元素,并用一个boolean函数(或者断言)返回true。缺省实现指定用其迭代器来遍历集合,在每个元素上调用断言( predicate),并利用迭代器的remove方法移除断言返回值为true的元素。其声明大致如下:

default boolean removeIf(Predicate<? super E> filter) {
    Objects.requireNonNull(filter);
    boolean result = false;
    for (Iterator<E> it = iterator(); it.hasNext(); ) {
        if (filter.test(it.next())) {
            it.remove();
            result = true;
        }
    }
    return result;
}

        这是适用于removeIf方法的最佳通用实现,但遗憾的是,它在某些现实的Collection实现中会出错。比如,以org.apache.commons.collections4.Collection.SynchronizedCollection为例,这个类来自Apache Commons类库,类似于java.util中的静态工厂Collections . synchronizedCollection。Apache 版本额外提供了利用客户端提供的对象(而不是用集合)进行锁定的功能。换句话说,它是-一个包装类,它的所有方法在委托给包装集合之前,都在锁定对象上进行了同步。

        Apache版本的SynchronizedCollection类依然有人维护,但是到编写本书之时,它也没有取代removeIf方法。如果这个类与Java 8结合使用,将会继承removeIf的缺省实现,它不会(实际上也无法)保持这个类的基本承诺:围绕着每一个方法调用执行自动同步。缺省实现压根不知道同步这回事,也无权访问包含该锁定对象的域。如果客户在SynchronizedCollection实例上调用removeIf方法,同时另一个线程对该集合进行修改,就会导致ConcurrentModificationException或者其他异常行为。

        为了避免在类似的Java平台类库实现中发生这种异常,如Collections.synchronizedCollection返回的包私有类,JDK维护人员必须覆盖默认的removeIf实现,以及像它一样的其他方法,以便在调用缺省实现之前执行必要的同步。不属于Java平台组成部分的预先存在的集合实现,过去无法做出与接口变化相类似的改变,现在有些已经可以做到了。

        有了缺省方法,接口的现有实现就不会出现编译时没有报错或警告,运行时却失败的情况。这个问题虽然并非普遍,但也不是孤立的意外事件。Java 8在集合接口中添加的许多方法是极易受影响的,有些现有实现已知将会受到影响。

        建议尽量避免利用缺省方法在现有接口,上添加新的方法,除非有特殊需要,但就算在那样的情况下也应该慎重考虑:缺省的方法实现是否会破坏现有的接口实现。然而,在创建接口的时候,用缺省方法提供标准的方法实现是非常方便的,它简化了实现接口的任务。

        还要注意的是,缺省方法不支持从接口中删除方法,也不支持修改现有方法的签名。对接口进行这些修改肯定会破坏现有的客户端代码。结论很明显:尽管缺省方法现在已经是Java平台的组成部分,但谨慎设计接口仍然是至关重要的。虽然缺省方法可以在现有接口,上添加方法,但这么做还是存在着很大的风险。就算接口中只有细微的缺陷都可能永远给用户带来不愉快;假如接口有严重的缺陷,则可能摧毁包含它的API。

        因此,在发布程序之前,测试每一个新的接口就显得尤其重要。程序员应该以不同的方法实现每一个接口。最起码不应少于三种实现。编写多个客户端程序,利用每个新接口的实例来执行不同的任务,这一点也同样重要。这些步骤对确保每个接口都能满足其既定的所有用途起到了很大的帮助。它还有助于在接口发布之前及时发现其中的缺陷,使你依然能够轻松地把它们纠正过来。或许接口程序发布之后也能纠正,但是千万别指望它啦!

Effective JAVA 笔记 快速回想一下effective java 阅读详情

相关推荐

vivado安装空间与依赖要求:入门须知要点

准备安装Vivado时,需重点关注系统空间和依赖环境的配置。结合vivado安装教程,详细说明最低磁盘要求、内存配置及操作系统兼容性,帮助新手快速搭建开发环境,避免常见安装失败问题。

weixin_34725745的博客 1573

Effective Java笔记:为后代设计接口

方法的新增行为在实现类中是"隐形的",它可能会在实现类中引入行为变化,而开发或维护人员不一定意识到这些变化。例如,新增的方法可能需要特定的上下文或数据,而某些实现类可能没有这些条件。如果需要在现有接口上扩展新功能,而这个功能对现有实现类的意义不强,可以选择创建一个新接口,并用它补充现有接口。如果需要为接口提供某些通用功能,可以设计一个抽象类来实现接口,同时为需要默认行为的子类提供基本实现。接口应该是一个明确的"契约",只是声明 “对象必须支持的方法”,具体如何实现则由实现类负责。的使用提出了重要的建议。

eclipseC的博客 802

第十九届全国大学生智能车竞赛越野信标 硬件篇

全国大学生智能汽车竞赛,越野信标组

2301_77568650的博客 4115

《Effective Java》解读第21条:为后代设计接口

摘要: 接口设计需具备前瞻性,因其发布后难以修改。Java 8的默认方法虽缓解了接口演进的兼容性问题,但需谨慎使用:应作为后期修正工具而非初始设计手段,避免多重继承冲突。核心建议包括:优先通过抽象骨架类(如AbstractList)提供基础实现,减少实现负担;默认方法需确保安全、高效且逻辑合理;设计时假设接口不可更改,严格规划方法。最终目标是构建稳定且可扩展的接口,平衡灵活性与兼容性。

Cosmoshhhyyy的博客 1065

MCP4728 电路及stm32F103程序移植

写在前面 通过优快云查到一些MCP4728 的程序,结合程序及datasheet对于驱动的描述,理清了思路 感谢开路者! MCP4728的电路比较简单,见下文描述 应用电路 datasheet: 实际测试电路: SCL接stm32的PB10,SDA接PB11 RDY/BSY引脚和LDCA引脚,悬空 解释见截图: MCP4728地址 选择任意输出通道写入DAC输入寄存器 应用程序 int mcp4728_write_all_channel(float vol1, float vol2, fl

u013074298的专栏 5425

五、2K0300 久久派开发板的GPIO控制与Shell脚本自动化实战

本文详细介绍了基于龙芯2K0300处理器的久久派开发板的GPIO控制方法,通过sysfs文件系统实现LED控制和传感器读取。重点讲解了Shell脚本自动化实战,包括LED闪烁、流水灯效果和传感器数据采集,为物联网项目开发提供完整解决方案。

silver的专栏 687

Effective Java(第三版) 学习笔记 - 第四章 类和接口 Rule20~Rule25

Effective Java(第三版) 学习笔记 - 第四章 类和接口 Rule20~Rule25 本文主要介绍了类和接口相关的内容

weixin_44453385的博客 883

OpenCV中SGBM中BT代价计算

这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入 欢迎使用Markdown编辑器 你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Mar

qq_27606639的博客 5977

Effective Java 读书笔记

Effective Java 读书笔记

SteveJrong's Blog 1165

基于微信小程序的扫码签到系统源码

大等于jdk1.8,大于mysql5.5,idea(eclipse),微信开发者工具。代码注释齐全,没有多余代码,适合学习(毕设),二次开发,包含论文技术相关文档。签到管理:新增签到,点击查看码展示二维码(有时效性)springboot mybatis 小程序。签到管理:查看用户创建的签到,可删除。用户管理:查看注册用户信息,及删除。签到记录:查看用户签到记录:可删除。个人信息:展示个人信息,可修改。统计分析:查看用户,签到数量。签到记录:查看用户签到记录。登录注册(含授权登录)我的签到:查看签到记录。

wfuhui的博客 5224

LangGraph 实战教程:搭建一个智能办公多Agent协作平台

只存储必要的信息:不要把所有的原始数据都存储在状态中,比如销售数据可以存储在数据库或向量数据库中,状态中只存储数据的 ID 或摘要。使用类型提示:避免类型错误,提高代码的可维护性。支持增量更新:LangGraph 默认支持状态的增量更新(通过reduce函数),比如messages列表可以通过追加新消息的方式更新,而不是每次都重新创建整个列表。Normal Edge 的定义非常简单,只需要在StateGraph对象(稍后会详细讲解)上调用add_edge# 创建一个 StateGraph 对象。

SuperAGI2025 221

Effective Java笔记:接口优于抽象类

在 《Effective Java 第三版》中,作者 Joshua Bloch 对“接口优于抽象类”这一原则有着深入的探讨。在理解“接口优于抽象类”之前,我们需要明确二者的本质区别:书中的核心观点是:接口提供了更大的灵活性、更广泛的适用性以及更好的未来兼容性。因此,Joshua Bloch 在条目20中推荐开发者优先选择接口,原因如下:示例:接口的多重继承 相比抽象类,接口让一个类可以轻松拥有“多个行为”(复合式能力),而不需要受到单继承的限制。 书中例子常见的场景: 和 模式相比抽象类,接口更加关注对

eclipseC的博客 1021

【DeepSeek应用实践】手把手教程:用 AnythingLLM + Ollama + DeepSeek-R1 搭建本地企业知识库

在众多的技术方案中,我们选择了 AnythingLLM、Ollama 和 DeepSeek-R1 这一组合来搭建本地知识库。Ollama 作为一个轻量级的本地化大语言模型部署工具,支持多种模型,易于安装和使用,能够快速在本地运行强大的语言模型。DeepSeek-R1 是一个专为知识库问答设计的检索增强生成(RAG)模型,它结合了检索和生成的优势,能够快速从知识库中检索相关信息并生成精准答案。而 AnythingLLM 则是一个用户友好的界面工具,可以方便地连接 Ollama 和 DeepSeek-R1

寻道AI,探索AI无限可能! 2568

Effective Java读书笔记

第一章 引言 本文用来记录Effective Java学习过程中的各个知识点,受此时能力所限,有些点可能讲的不太清楚,或者理解有错误的地方,请多多指教! 第二章 创建和销毁对象 第一条 用静态工厂方法代替构造器 可参考文章:https://blog.youkuaiyun.com/u014129886/article/details/89670049 总而言之,静态工厂方法和共有构造器各有各的用处,我们需要理解他们各自的长处,静态工厂经常更加合适。 此处的静态工厂方法与设计模式中的工厂模式不同,这里是一种构造

逆水行舟,不进则退 1441

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

Effective Java 3rd 条目21 为后代设计接口

在Java8之前,添加方法到接口而没有破坏已存实现,是不可能的。如果你添加了一个新方法到接口,已存实现通常缺少这个方法,导致编译时期错误。在Java8中,添加了默认方法构造(default method construct)[JLS 9.4],让方法添加到已存接口。但是添加新方法到已存接口充满了危险性。 默认方法的声明包括一个默认实现(default implementation),实现接口的所...

tigershin的专栏 287

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

《Effective java》第二版阅读笔记

18.接口优于抽象类 接口和抽象类都是java中定义类型、扩展功能的机制。 两者主要区别在于接口中全部是抽象方法,抽象类中可以包含抽象方法,也可以包含非抽象方法。 而接口优于抽象类的原因是,类可以实现多个接口,但只能继承一个抽象类,抽象类的使用受限。 假使对一个类进行扩展功能,可在implements后新增接口实现,如Comparable引进到java中后,更新了许多现有类。同时接口也是mixin...

张晨雪的博客 664

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

《Effective Java》学习笔记--第4部分 类和接口设计实现最佳实践

Effective Java》共有多个章节,每个章节提供了若干条建议或最佳实践,整理了对应章节关键的实践内容,用于自己后续代码开发过程中,参考对照,自查代码习惯,从而提升输出的代码质量。《Effective Java》第4部分“类和接口”深入探讨了如何设计高质量的类和接口。在 Java 中,类和接口是构建程序的核心单元,良好的类和接口设计能够增强代码的可维护性、可扩展性和可重用性。书中通过一系列的最佳实践和设计建议,帮助我们构建清晰且高效的类和接口。

weixin_37693760的博客 1680

Effective Java 第三版 中文翻译

effective-java-third-edition 介绍 Effective Java 第三版全文翻译,纯属个人业余翻译,不合理的地方,望指正,感激不尽! 目录 推荐序 前言 致谢 第一章 引言 第二章 创建和销毁对象   本章涉及创建和销毁对象,包括何时以及如何创建它们,何时以及如何避免创建它们,如何确保它们被及时销毁,以及如何管理在销毁之前必须进行的清理操作。 第1项:考虑静态工...

Coloured_Glaze的博客 3861

带你快速看完9.8分神作《Effective Java》—— 类和接口篇

???? Java学习:Java从入门到精通总结 ???? Spring系列推荐:Spring源码解析 ???? 最近更新:2022年1月7日 ???? 个人简介:通信工程本硕????、阿里新晋猿同学????。我的故事充满机遇、挑战与翻盘,欢迎关注作者来共饮一杯鸡汤 ???? 点赞 ???? 收藏 ⭐留言 ???? 都是我最大的动力! 15 使类和成员的可访问性最小化 面向对象语言设计时的两大“法宝”就是封装和解耦。其中,封装可以隐藏组件所有的实现细节,把API与实现清晰隔离开,因此也就解除组成系

如切如磋,如琢如磨 1957

Effective Java读书笔记(一):类、接口、对象

前言“可能有人认为我不需要任何Java方面的书籍,但是我需要这本” - James GoslingJava领域有几本被奉为圣经的书籍,其中(我认为)最著名的两本是《Thinking in Java》以及《Effective Java》。如果说Java编程思想教会我们Java这门语言,那么Effective Java则教会我们如何写出更好的Java语言程序。这本书对于API开发程序员更为对口,但是对于

leelit笔记本 797

笔记《Effective Java》02:对所有对象都通用的方法(文末抽奖)

然而,它没有达到这个目的,主要的缺陷是缺乏 clone 方法,而 Object 类中的 clone 方法是受保护的。相反,请使用基本类型的封装类中的静态compare方法,或使用Comparator接口中的比较器构造方法。他们不需要类型转换。Java8中,Comparator接口提供了一组比较构造器方法,这些比较器可以用来实现Comparable接口所要求的compareTo方法,不过性能上会稍微慢一些。虽然Object类提供了toString方法的一个实现,但他返回的字符串通常不是类的用户所希望看到的。

有一只柴犬的专栏 1301

《Effective Java》读书笔记三

一、明确接口的核心作用定义类型:接口的主要目的是为了定义一种特定的行为规范和类型标识。它描述了一组方法签名,任何实现该接口的类都必须提供这些方法的具体实现。通过接口,我们可以以一种统一的方式来处理不同的实现类,而无需关心具体的实现细节。类型标识的重要性:接口作为一种类型,可以在代码中用于变量声明、方法参数和返回值类型等。这使得代码更加灵活和可扩展,因为可以在运行时根据实际情况传入不同的实现类,而无需修改调用代码。二、避免不恰当的使用不要在接口中定义常量以外的变量:接口不应该被用作存储数据的地方。

qq_41831136的博客 803

【读书笔记】Effective Java(类和接口)

读书笔记-Effective Java(类和接口)

我的博客 392

effective Java 学习笔记(第二弹)

整理自《effective Java 中文第3版》本篇笔记整理第3,4章的内容。

Willow的博客 1168

《Effective Java》读书笔记

优先使用接口、泛型、静态工具类...

qq_43336396的博客 750
上一篇: Effective Java笔记(20)接口优于抽象类
下一篇: Effective Java笔记(22)接口只用于定义类型
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值