当前位置: 首页 > 知识库问答 >
问题:

为什么@FunctionalInterface没有用在JDK中所有符合条件的接口上?

易飞文
2023-03-14

Java8为我们提供了许多有趣的方法来使用函数接口,并与它们一起使用了一个新的注释:@functionalinterface。它的工作是告诉编译器,如果我们没有遵守函数接口的规则(只有一个需要重写的抽象方法),就对我们大喊大叫。

java.util.function包中有43个带有这个注释的接口。在JDK.1.8.0/src中搜索@functionalinterface只有57次点击。为什么其他可以添加@functionalinterface的接口(如AutoCloseable)仍然缺少它?

注释文档中有一点模糊的提示:

向任何已发布的接口添加抽象方法难道不会使任何实现它的人陷入困境吗,不管是函数性的还是非函数性的?我觉得很愤世嫉俗,假设他们没有费心去追捕他们,但还有什么别的解释呢?

更新:翻看“‘可比’应该是一个‘功能接口’吗?”我发现我还有一些唠叨的问题。当一个方法接口和一个函数接口在结构上相同时,还有什么不同呢?区别仅仅是名字吗?Comparable和Comparator在语义上非常接近于同一。结果发现它们在结构上是不同的,但仍然不是最好的例子...

是否存在这样的情况:SMI在结构上很好地用作功能接口,但在接口和方法名称的语义意义上仍然不受欢迎?或者JavaDocs隐含的契约?

共有1个答案

单嘉泽
2023-03-14

那么,如果您假设总是给定意图,那么记录意图的注释将是无用的。

您将示例命名为autocloseable,这显然不是要作为函数实现的,因为有runnable,这对于具有()->void签名的函数来说要方便得多。目的是让实现autocloseable的类管理外部资源,而通过lambda表达式实现的匿名类不这样做。

一个更清楚的例子是comparableinterface不仅不打算作为lambda表达式实现,而且不可能使用lambda表达式正确地实现它。

>

  • 接口具有编程语言语义,例如自动关闭迭代(您自己的接口不太可能发生这种情况)
  • 不希望接口具有任意实现和/或更多地是实际实现的标识符,例如java.net.protocolfamilyjava.lang.Reflect.GenericArrayType(请注意,后者还将继承GetTypeName()Default实现,因为它依赖于ToString())对于lambda实现是无用的)
  • 接口的实例应具有标识,例如java.net.protocolfamilyjava.nio.file.WatchEvent.Modifier等。请注意,这些通常由枚举实现

    另一个例子是java.time.chrono.era,它碰巧只有一个abstract方法,但它的规范说“可以使用==运算符比较era的实例。”

    库维护器有一个包含200多个候选类型的大型代码库,而不是为每个接口讨论是否应该对其进行注释的资源,因此将重点放在在函数上下文中使用的主要候选类型上。我确信,例如java.io.objectinputvalidationjava.lang.reflect.invocationhandler、jucrejectedexecutionhandler&ThreadFactory作为@functionalinterface并不差,但我不知道例如java.security.spec.ecfield是否是一个好的候选。库越通用,库的用户就越有可能回答他们感兴趣的特定接口的问题,但坚持要求库维护人员回答所有接口的问题是不公平的。

    在此上下文中,将@functionalinterface的存在看作是一条消息,表明interface肯定是要与lambda表达式一起使用的,而不是将注释的不存在看作不是要以这种方式使用的指示符,这更有意义。这与编译器处理它的方式完全相同,您可以使用lambda表达式实现每个抽象方法接口,但当注释出现时,它将确保您可以以这种方式使用此接口

  •  类似资料:
    • 问题内容: 在Java has 方法中,但是,它仅在诸如或的关联容器中使用。为什么要这样设计?具有方法的界面看起来更优雅。 问题答案: 在我看来,主要的论据是,可以为任何Java对象计算出一个定义明确的默认值,以及一个同样定义明确的。根本没有充分的理由要保留所有对象的该功能,当然也有很多理由 不 保留此功能。因此,这本书毫无疑问。

    • 我在一些文章中读到,在一些语言中,比如JavaScript,赋值运算符可以用于条件语句。我想知道那次行动背后的逻辑是什么?据我所知,条件检查语句中只允许使用比较运算符。

    • 为了防止实现细节泄漏,可以实现,而不是返回,然后需要从接口实现。因此,无论内部数据结构如何管理,对元素的访问都是通过进行的。 对于Java8,可能希望将添加到。(另请参阅《Java8lambdas》一书中关于支持的建议)。虽然添加方法并不困难(我也读过关于为什么Iterable不提供流的问题),但奇怪的是Java没有为添加接口来镜像思想。(好吧,可能有一个不同的名称,因为是为了永远使用CORBA的

    • 当Java文件是接口时,如: 我用编译,然后用反汇编,输出如下: 而当Java文件是类时,如: 使用,然后使用进行反汇编,输出如下: 为什么接口的类文件中不包括? JDK版本:1.8.0_311

    • 但是我发现我不能用围棋做同样的事情,我必须写一个if-else语句。我只是想知道为什么在围棋世界里不存在这种情况(是否有一些设计原则来解释这种情况)

    • 我想只从我的两个对象数组和中得到那些符合标准的子文档。即使我已经找到了这个stackoverflow答案#2(根据标准查找猫鼬子文档),它对我来说并不像期望的那样工作,或者我错过了一些东西。 我的文档如下所示: 它将在和中打印项目及其所有子文档。但是,我只想获取与给定上载id匹配的子文档。我做错了什么? 编辑:这个问题是指用猫鼬来解决它。我不能在Mongoose中使用这个问题的集合语句(只检索Mo