为什么在JDK中的所有接口上都没有使用@FunctionalInterface符合要求? [英] Why isn't @FunctionalInterface used on all the interfaces in the JDK that qualify?

查看:366
本文介绍了为什么在JDK中的所有接口上都没有使用@FunctionalInterface符合要求?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Java 8为我们提供了许多有趣的方式来使用功能性接口,并为它们添加了新的注释: @ FunctionalInterface 。它的工作是告诉编译器如果我们不遵守一个函数接口的规则(只有一个抽象方法需要重写请求),我们会大声吼叫。



有是 java.util.function包中的43个接口与此批注。对 @FunctionalInterface 的jdk.1.8.0 / src搜索只能找到57个命中。为什么添加了 @FunctionalInterface 的其他接口(例如AutoCloseable)仍然缺少它?



注释文档

a>:



一种信息注释类型,用于表示接口类型声明是意图是一个功能接口



有没有很好的理由不能打算我设计的接口(它可能只是一个功能接口)不能作为一个接口使用?除了没有意识到它可以被添加以外,还有什么迹象表明它没有?

是不是将抽象方法添加到任何公布的接口中去实现它的任何实现它的功能?我感到愤世嫉俗,假设他们没有打扰他们,但是还有什么其他解释?

更新:仔细查看< a'href =https://stackoverflow.com/questions/25222575/should-comparablet-be-a-functional-interface>应该'比较''是一个'功能界面'?我发现我仍然有唠叨的问题。当一个单一方法接口和一个功能接口在结构上是相同的时候,还有什么不同?差别只是名字吗? Comparable和Comparator在语义上相近。结果发现它们在结构上是不同的,尽管如此仍然不是最好的例子......



有没有一种情况是SMI在结构上可以用作功能接口但仍然不鼓励超越界面名称和方法的语义含义?或者也许是Javadocs暗含的契约?

解决方案

那么,记录意图的注释将是无用的,如果您认为存在总是给出这个意图。



您将示例命名为 AutoCloseable ,显然不是意图以 Runnable 的形式实现,这对于具有() - > void 签名。它旨在实现一个实现 AutoCloseable 的类来管理外部资源,匿名类通过lambda表达式实现的外部资源不会执行。



一个更清晰的例子是 Comparable ,一个 interface 不仅不打算作为lambda表达式来实现,使用lambda表达式正确执行它。






未标记界面的可能原因 @FunctionalInterface 举例:




  • interface 具有编程语言语义,例如 AutoClosable Iterable (这不太可能发生在您自己的界面上)
  • 不希望接口具有任意的实现和/或更多的标识符而不是实际的实现,例如 java.net.ProtocolFamily java.lang.reflect.GenericArrayType (注意后者也会继承 > > getTypeName()对于lambda实现依赖于 toString() code>)

  • 这个接口的实例应该有一个标识,例如> java.net.ProtocolFamily java.nio.file.WatchEvent.Modifier 等。请注意,这些通常是实现的由 enum



    另一个例子是 java.time.chrono.Era 这恰好只有一个 abstract 方法,但其规范中指出: Era 的实例可以使用 运算符。


  • 界面旨在改变一个执行接口而没有继承/实现任何其他内容的操作是没有意义的操作,例如 java.rmi.server.Unreferenced

  • 它是类的常见操作的抽象,它不仅仅是这些操作, java.io.Closeable java.io.Flushable java.lang.Readable

  • 预期的继承是契约的一部分,并且禁止lambda表达式实现,例如在 java.awt 中: ActiveEvent 应该由 AWTEvent PrinterGraphics Graphics ,同样适用于 java.awt.print.PrinterGraphics (嘿,两个接口完全相同的事情......),wheras javax.print.FlavorException 应该由 javax.print.PrintException 子类实现
  • 我不知道各种事件侦听器接口是不是用$ @FunctionalInterface 标记为与其他多方法事件侦听器对称,但不能是功能接口,但实际上事件侦听器是lambda表达式的良好候选者。如果您想在稍后时间移除侦听器,则必须存储该实例,但与此例不同。内部类监听器实现。
  • 库维护者拥有一个包含200多个候选类型的大型代码库,而不是为每个接口讨论的资源是否应该注释它,因此重点关注在功能上使用的主要候选人。我相信,例如 java.io.ObjectInputValidation java.lang.reflect.InvocationHandler ,juc RejectedExecutionHandler & ThreadFactory 不会像 @FunctionalInterface 那样坏,但我不知道是否 java.security.spec.ECField 是个不错的选择。图书馆越一般,图书馆的用户就越有可能为他们感兴趣的特定界面回答这个问题,但坚持要求不公平图书馆维护人员为所有接口回答它。



    在这种情况下,更有意义的是看到 @FunctionalInterface 作为一个消息,一个接口肯定可以和lambda表达式一起使用,而不是将注释作为一个指示符因为它不打算以这种方式使用。这与编译器处理它完全一样,可以使用lambda表达式实现每个抽象方法 interface ,但是当注释存在时,它将确保 >你可以这样使用这个接口



Java 8 gave us many fun ways to use functional interfaces and with them a new annotation: @FunctionalInterface. Its job is to tell the compiler to yell at us if we fail to stick to the rules of a functional interface (only one abstract method that needs overriding please).

There are 43 interfaces in the java.util.function package with this annotation. A search of jdk.1.8.0/src for @FunctionalInterface only turns up 57 hits. Why are the other interfaces (such as AutoCloseable) that could have added @FunctionalInterface still missing it?

There is a bit of a vague hint in the annotations documentation:

"An informative annotation type used to indicate that an interface type declaration is intended to be a functional interface"

Is there any good reason NOT to intend that an interface I've designed (that may simply happen to be a functional interface) not be used as one? Is leaving it off an indication of anything besides not realizing it could have been added?

Isn't adding abstract methods to any published interface going to screw anyone implementing it, functional or not? I feel cynical assuming they just didn't bother to hunt them all down but what other explanation is there?

Update: After looking over "Should 'Comparable' be a 'Functional interface'?" I find I still have nagging questions. When a Single Method Interface and a Functional Interface are structurally identical what's left to be different? Is the difference simply the names? Comparable and Comparator are close enough to the same semantically. Turns out they are different structurally though so still not the best example...

Is there a case when an SMI is structurally fine to use as a Functional Interface but still discouraged over the semantic meaning of the name of the interface and the method? Or perhaps the contract implied by the Javadocs?

解决方案

Well, an annotation documenting an intention would be useless if you assume that there is always that intention given.

You named the example AutoCloseable which is obviously not intended to be implemented as a function as there’s Runnable which is much more convenient for a function with a ()->void signature. It’s intended that a class implementing AutoCloseable manages an external resource which anonymous classes implemented via lambda expression don’t do.

A clearer example is Comparable, an interface not only not intended to be implemented as a lambda expression, it’s impossible to implement it correctly using a lambda expression.


Possible reasons for not marking an interface with @FunctionalInterface by example:

  • The interface has programming language semantics, e.g. AutoClosable or Iterable (that’s unlikely to happen for your own interfaces)
  • It’s not expected that the interface has arbitrary implementations and/or is more an identifier than the actual implementation, e.g. java.net.ProtocolFamily, or java.lang.reflect.GenericArrayType (Note that the latter would also inherit a default implementation for getTypeName() being useless for lambda implementations as relying on toString())
  • The instances of this interface should have an identity, e.g. java.net.ProtocolFamily, java.nio.file.WatchEvent.Modifier, etc. Note that these are typically implemented by an enum

    Another example is java.time.chrono.Era which happens to have only a single abstract method but its specification says "Instances of Era may be compared using the == operator."

  • The interface is intended to alter the behavior of an operation for which an implementation of the interface without inheriting/implementing anything else makes no sense, e.g. java.rmi.server.Unreferenced
  • It’s an abstraction of common operations of classes which should have more than just these operations, e.g. java.io.Closeable, java.io.Flushable, java.lang.Readable
  • The expected inheritance is part of the contract and forbids lambda expression implementations, e.g. in java.awt: ActiveEvent should be implemented by an AWTEvent, PrinterGraphics by a Graphics, the same applies to java.awt.print.PrinterGraphics (hey, two interfaces for exactly the same thing…), wheras javax.print.FlavorException should be implemented by a javax.print.PrintException subclass
  • I don’t know whether the various event listener interfaces aren’t marked with @FunctionalInterface for symmetry with other multi-method event listener that can’t be functional interfaces, but actually event listeners are good candidates for lambda expressions. If you want remove a listener at a later time, you have to store the instance but that’s not different to, e.g. inner class listener implementations.
  • The library maintainer has a large codebase with more than 200 candidate types and not the resources to discuss for every interface whether it should be annotated and hence focuses on the primary candidates for being used in a functional context. I’m sure, that, e.g. java.io.ObjectInputValidation, java.lang.reflect.InvocationHandler, juc RejectedExecutionHandler & ThreadFactory wouldn’t be bad as @FunctionalInterface but I have no idea whether, e.g. java.security.spec.ECField makes a good candidate. The more general the library is, the more likely users of the library will be able to answer that question for a particular interface they are interested in but it would be unfair to insist on the library maintainer to answer it for all interfaces.

    In this context it makes more sense to see the presence of a @FunctionalInterface as a message that an interface is definitely intended to be usable together with lambda expressions than to treat the absence of the annotation as an indicator for it’s being not intended to be used this way. This is exactly like the compiler handles it, you can implement every single abstract method interface using a lambda expression, but when the annotation is present it will ensure that you can use this interface in this way.

这篇关于为什么在JDK中的所有接口上都没有使用@FunctionalInterface符合要求?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆