Java 8 默认方法作为特征:安全吗?

2023-11-23

使用安全做法吗默认方法是穷人版本的特质在 Java 8 中?

有人声称这可能会让熊猫感到悲伤如果你只是为了使用它们,因为它很酷,但这不是我的意图。人们还经常提醒,引入默认方法是为了支持 API 演化和向后兼容性,这是事实,但这并不意味着将它们用作特征本身是错误或扭曲的。

I have 以下实际用例心里:

public interface Loggable {
    default Logger logger() {
        return LoggerFactory.getLogger(this.getClass());
    }
}

或者也许,定义一个PeriodTrait:

public interface PeriodeTrait {
    Date getStartDate();
    Date getEndDate();
    default isValid(Date atDate) {
        ...
    }
}

诚然,可以使用组合(甚至辅助类),但它看起来更冗长和混乱,并且不允许从多态性中受益。

So, 使用默认方法作为基本特征是否可以/安全,或者我应该担心不可预见的副作用吗?

几个问题on SO 与 Java 与 Scala 特征相关;这不是重点。我也不只是征求意见。相反,我正在寻找权威的答案或至少是现场洞察力:如果您使用默认方法作为公司项目的特征,它是否会成为定时炸弹?


简短的回答是:如果您安全地使用它们,那就安全了:)

尖刻的回答:告诉我什么you是指特征,也许我会给你一个更好的答案:)

严肃地说,“特质”这个词并没有明确的定义。许多 Java 开发人员最熟悉的是在 Scala 中表达的特征,但无论从名称上还是实际上来看,Scala 都不是第一种拥有特征的语言。

例如,在 Scala 中,特征是有状态的(可以有var变量);在《堡垒》中,它们是纯粹的行为。 Java 的带有默认方法的接口是无状态的;这是否意味着它们不是特质? (提示:这是一个棘手的问题。)

同样,在 Scala 中,特征是通过线性化组合而成的;如果上课A延伸特质X and Y,然后按顺序X and Y混合在一起决定了之间如何发生冲突X and Y已解决。在 Java 中,不存在这种线性化机制(它被拒绝,部分原因是它太“不像 Java”。)

向接口添加默认方法的直接原因是为了支持界面演变,但我们很清楚我们正在超越这个范围。无论您认为这是“界面进化++”还是“特征--”,都是个人解释的问题。因此,要回答您有关安全的问题……只要您坚持该机制实际支持的内容,而不是试图将其扩展到它不支持的内容,就应该没问题。

一个关键的设计目标是,从client对于接口来说,默认方法应该与“常规”接口方法没有区别。因此,方法的默认性仅对designer and 实施者界面的。

以下是一些完全符合设计目标的用例:

  • 界面演变。在这里,我们向现有接口添加一个新方法,该接口根据该接口上的现有方法有一个合理的默认实现。一个例子是添加forEach方法Collection,其中默认实现是根据以下形式编写的iterator()方法。

  • “可选”方法。在这里,接口的设计者是说“如果实现者愿意接受所带来的功能限制,则不需要实现此方法”。例如,Iterator.remove被给予默认值,抛出UnsupportedOperationException;因为绝大多数的实现Iterator无论如何都有这种行为,默认情况下该方法本质上是可选的。 (如果行为来自AbstractCollection被表示为默认值Collection,我们可以对变异方法做同样的事情。)

  • 方便的方法。这些方法纯粹是为了方便起见,通常也是通过类的非默认方法来实现的。这logger()第一个示例中的方法是对此的合理说明。

  • 组合器。这些是基于当前实例实例化接口的新实例的组合方法。例如,方法Predicate.and() or Comparator.thenComparing()是组合器的例子。

如果您提供默认实现,您还应该为默认提供一些规范(在 JDK 中,我们使用@implSpecjavadoc 标签)以帮助实现者了解他们是否想要重写该方法。一些默认值,例如便捷方法和组合器,几乎永远不会被覆盖;其他的,比如可选方法,经常被覆盖。您需要提供关于默认承诺执行的操作的足够规范(而不仅仅是文档),以便实现者可以就是否需要覆盖它做出明智的决定。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java 8 默认方法作为特征:安全吗? 的相关文章

随机推荐

  • R:合并同一数据表中的行,连接某些列

    我在 R 中有我的数据表 我想合并具有相同的行customerID 然后连接其他合并列的元素 我想从这里开始 title author customerID 1 title1 author1 1 2 title2 author2 2 3 t
  • 在 Android 中运行单元测试时,意图解析为不同的进程

    我有一个使用两个活动的小型应用程序 这两个活动都继承自 MapActivity 并显示地图 com google android maps 由于 Android 谷歌地图文档说 每个仅支持一个 MapActivity 过程 多个地图活动 同
  • 强制用户在 Java 中填充 varargs 参数的好方法[重复]

    这个问题在这里已经有答案了 我想强制用户在调用构造函数时填写可选参数 public MyClass String params this params params 目前 以下代码有效 new MyClass 我想阻止它 我想到了这一点 p
  • Biopython SeqIO 到 Pandas Dataframe

    我有一个可以轻松解析的 FASTA 文件SeqIO parse 我对提取序列 ID 和序列长度感兴趣 我用这些行来做到这一点 但我觉得它太重了 两次迭代 转换等 from Bio import SeqIO import pandas as
  • 用星号屏蔽Python中的用户输入[重复]

    这个问题在这里已经有答案了 我试图用星号掩盖用户在 IDLE 中输入的内容 这样他们周围的人就看不到他们正在输入 已经输入的内容 我正在使用基本的原始输入来收集他们输入的内容 key raw input Password 用户输入密码后理想
  • QSignalMapper 是如何工作的?

    我在这里发帖后 将信号和槽关联到动态创建的 qcheckbox我需要关联 信号clicked 当我点击一个qCheckBox我的职能cliqueCheckBox QTableWidget monTab int ligne QCheckBox
  • Oracle SQL 中的小于或等于

    updated date 08 Jun 2010 我有一个这样的查询 select from asd whre updated date lt todate 08 Jun 2010 dd MM yy 但我没有得到任何结果 它只有在以下情况下
  • C# 线程和阻塞 [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心以获得指导 我想知道哪种方法是以线程安
  • Openlayers:矢量特征而不是标记

    我想在地图上放置一个符号 例如 到目前为止我已经使用了 OpenLayersOpenLayers Layer Markers 代码如下所示 map new OpenLayers Map map layer new OpenLayers La
  • 如何在颤动中设置下拉弹出窗口的动态高度

    我是颤振开发的新手 我正在使用我的应用程序的下拉按钮 打开下拉菜单时 弹出对话框中的文本被剪切 下面我附上了带有编码的屏幕截图 请指导我解决这个问题 DropdownButtonHideUnderline child new Dropdow
  • 赋值<指向常量数组的指针> = <指向数组的指针>:不兼容的指针

    当我编译这样的东西时 double da 3 2 3 4 double pda 3 da double const cpda 3 pda gcc warning MSVC ok 海湾合作委员会警告我 warning initializati
  • 如何调试Python中的MemoryError?跟踪内存使用情况的工具?

    我有一个 Python 程序 当我向它提供一个大文件时 它会因 MemoryError 而终止 有没有什么工具可以用来找出内存的使用情况 该程序在较小的输入文件上运行良好 该程序显然需要一些可扩展性改进 我只是想弄清楚在哪里 正如一位智者曾
  • 如何确定 MS SQL Server 2005 中表值变量的内部名称

    可以使用以下命令确定临时表的名称 例如 t1 select TableName Name from tempdb sys tables where Object ID object id tempDB dbo t1 如何找到表值变量的名称
  • 去除大量数字(big.Int)

    我正在尝试将两个大数相除 例如 尝试将 50 除以 18 并且我设置了两个 big Int 变量 first MulRange 1 50 second MulRange 1 18 如何划分数字 最好是整数除法 Thanks 我怎样才能划分数
  • 如何在 Objective-C 中的两个类之间进行引用?

    我正在开发一个 iPhone 应用程序 我对 Objective C 以及 class h 和 class m 结构有点陌生 现在 我有两个类 它们都需要具有另一个类型的变量 但这似乎是不可能的 如果在class1 m 或class2 m
  • 列出 javascript 中所有内置函数?

    js 有没有办法列出所有内置函数及其参数列表上的一些信息 我真的找不到任何关于反射来做这类事情的东西 编辑 Math sin之类的函数其实就是我要列出的 实际上都是内置函数 也许是这样的 for var x in window if win
  • 确定文件是否正在 Windows 上的 Perl 中使用

    我正在编写一些 Perl 它获取 Windows Media Center 上录制的电视节目 并根据某些条件移动 重命名 删除它们 由于 Perl 运行相当频繁 我想清楚地确定该文件是否正在使用 换句话说 节目正在录制过程中 这样我就可以避
  • Python 3:UnboundLocalError:赋值之前引用的局部变量[重复]

    这个问题在这里已经有答案了 下面的代码给出了错误UnboundLocalError local variable Var1 referenced before assignment Var1 1 Var2 0 def function if
  • 如何使用 Perl 从文本文件中提取 IP 地址?

    如何从每行都有 IP 地址的文本文件中提取 IP 地址 我想提取 IP 然后在单独的文件中列出 IP 地址 包含 IP 的文本文件采用以下格式 主机 somehost com 192 168 1 1 已启动 0 20 秒延迟 主机 10 1
  • Java 8 默认方法作为特征:安全吗?

    使用安全做法吗默认方法是穷人版本的特质在 Java 8 中 有人声称这可能会让熊猫感到悲伤如果你只是为了使用它们 因为它很酷 但这不是我的意图 人们还经常提醒 引入默认方法是为了支持 API 演化和向后兼容性 这是事实 但这并不意味着将它们