为什么不在 JDK 中所有符合条件的接口上使用 @FunctionalInterface?
Why isn't @FunctionalInterface used on all the interfaces in the JDK that qualify?
Java 8 为我们提供了许多有趣的方法来使用函数式接口以及一个新的注解:@FunctionalInterface。它的工作是告诉编译器如果我们不遵守功能接口的规则(请只需要覆盖一个抽象方法)就对我们大喊大叫。
有 个带有此注释。在 jdk.1.8.0/src 中搜索 @FunctionalInterface
仅出现 57 次匹配。为什么其他可以添加的接口(例如 AutoCloseable)@FunctionalInterface
仍然没有添加?
annotations documentation中有一点模糊的提示:
"An informative annotation type used to indicate that an interface type declaration is intended to be a functional interface"
有什么充分的理由不打算我设计的界面(可能只是碰巧是一个功能界面)不被用作一个界面?除了没有意识到它可以被添加之外,是否将其关闭表明有任何迹象?
向任何已发布的接口添加抽象方法是否会搞砸任何实现它的人,无论功能与否?假设他们只是懒得去追捕他们,我感到愤世嫉俗,但还有什么其他解释?
更新: 看完"Should 'Comparable' be a 'Functional interface'?",我发现我还有一些问题。当单一方法接口和功能接口在结构上相同时,还有什么不同之处呢?区别仅仅是名字吗? Comparable 和 Comparator 在语义上足够接近。事实证明它们在结构上有所不同,但仍然不是最好的例子......
是否存在这样一种情况:SMI 在结构上可以很好地用作功能接口,但仍然不鼓励接口名称和方法名称的语义?或者可能是 Java 文档隐含的合同?
计划扩张。仅仅因为接口现在符合 SMI 的要求并不意味着以后不需要扩展。
好吧,如果您假设总是给出该意图,那么记录意图的注释将毫无用处。
您将示例命名为 AutoCloseable
,这显然 不是 打算作为函数实现的,因为 Runnable
对于函数来说更方便带有 ()->void
签名。它的目的是 class 实现 AutoCloseable
管理外部资源,而通过 lambda 表达式实现的匿名 classes 则不会。
一个更清楚的例子是Comparable
,一个interface
不仅不打算作为lambda表达式来实现,而且使用lambda表达式也不可能正确地实现它。
未将 interface
标记为 @FunctionalInterface
的可能原因示例:
interface
具有编程语言语义,例如AutoClosable
或 Iterable
(您自己的界面不太可能发生这种情况)
- 预计
interface
不会有任意实现 and/or 与其说是实际实现,不如说是一个标识符,例如java.net.ProtocolFamily
或 java.lang.reflect.GenericArrayType
(请注意,后者还将继承 default
实现,因为 getTypeName()
对于依赖于 toString()
的 lambda 实现无用)
这个 interface
的实例应该有一个标识,例如java.net.ProtocolFamily
、java.nio.file.WatchEvent.Modifier
等。请注意,这些通常由 enum
实现
另一个例子是 java.time.chrono.Era
,它恰好只有一个 abstract
方法,但是 its specification 说“Era
的实例可以使用 ==
运算符。”
interface
旨在改变一个操作的行为,在没有 inheriting/implementing 的情况下实现 interface
是没有意义的,例如java.rmi.server.Unreferenced
- 它是对classes常用操作的抽象,它应该不止这些操作,例如
java.io.Closeable
、java.io.Flushable
、java.lang.Readable
- 预期的继承是契约的一部分,并禁止 lambda 表达式实现,例如在
java.awt
中:ActiveEvent
应该由AWTEvent
实现,PrinterGraphics
由Graphics
实现,同样适用于java.awt.print.PrinterGraphics
(嘿,两个interface
s 对于完全相同的事情...),wheras javax.print.FlavorException
应该由 javax.print.PrintException
subclass 实现
- 不知道是不是各种事件监听器接口没有标上
@FunctionalInterface
是为了和其他不能是函数式接口的多方法事件监听器对称,其实事件监听器是不错的选择对于 lambda 表达式。如果您想稍后删除侦听器,则必须存储实例,但这与例如内部 class 侦听器实现。
库维护者拥有超过 200 种候选类型的大型代码库,没有资源来讨论每个 interface
是否应该注释,因此专注于成为的主要候选者在功能上下文中使用。我敢肯定,例如java.io.ObjectInputValidation
, java.lang.reflect.InvocationHandler
, juc RejectedExecutionHandler
& ThreadFactory
不会像 @FunctionalInterface
那样糟糕,但我不知道是否,例如java.security.spec.ECField
是一个很好的候选人。图书馆越通用,图书馆的用户就越有可能针对他们感兴趣的特定 interface
回答该问题,但是坚持要求图书馆维护者回答 [=] 是不公平的80=]所有 接口。
在这种情况下,将 @FunctionalInterface
的存在看作是一条消息,表明 interface
绝对旨在与 lambda 表达式一起使用,而不是将 @FunctionalInterface
的不存在视为更有意义注释作为指示符,因为它不打算以这种方式使用。这与编译器处理它的方式完全一样,您可以使用 lambda 表达式实现每个抽象方法 interface
,但是当存在注释时,它将 确保 您可以使用它interface
这样。
在java8中,函数式接口是只有一个抽象方法的接口,称为函数式方法,lambda表达式的参数和return类型匹配。
java.util.function
包含 JDK 使用的通用功能接口,也可供最终用户使用 。虽然它们不是 lambda 表达式可能适用的完整功能接口集,但它们提供的功能足以满足常见需求。当现有集不够时,您可以自由创建自己的功能接口。
有许多这样的接口值得被指定为功能接口,但是java.util.function
包已经为我们几乎所有的目的提供了功能接口。
例如查看以下代码。
public interface Comparable<T> {
public int compareTo(T o);
}
@FunctionalInterface
public interface ToIntFunction<T> {
int applyAsInt(T value);
}
public static void main(String[] args){
ToIntFunction<String> f = str -> Integer.parseInt(str);
Comparable<String> c = str -> Integer.parseInt(str);
}
Comparable
也可以获取一个对象并派生一些 int 类型的值,但是提供了一个更通用的专用接口 ToIntFunction
来执行此任务。 没有硬性规定所有应得的接口都应使用 @FunctionalInterface
注释,但要获得 lambda 功能的优势,接口应满足 FunctionalInterface 定义的所有标准。
Java 8 为我们提供了许多有趣的方法来使用函数式接口以及一个新的注解:@FunctionalInterface。它的工作是告诉编译器如果我们不遵守功能接口的规则(请只需要覆盖一个抽象方法)就对我们大喊大叫。
有 @FunctionalInterface
仅出现 57 次匹配。为什么其他可以添加的接口(例如 AutoCloseable)@FunctionalInterface
仍然没有添加?
annotations documentation中有一点模糊的提示:
"An informative annotation type used to indicate that an interface type declaration is intended to be a functional interface"
有什么充分的理由不打算我设计的界面(可能只是碰巧是一个功能界面)不被用作一个界面?除了没有意识到它可以被添加之外,是否将其关闭表明有任何迹象?
向任何已发布的接口添加抽象方法是否会搞砸任何实现它的人,无论功能与否?假设他们只是懒得去追捕他们,我感到愤世嫉俗,但还有什么其他解释?
更新: 看完"Should 'Comparable' be a 'Functional interface'?",我发现我还有一些问题。当单一方法接口和功能接口在结构上相同时,还有什么不同之处呢?区别仅仅是名字吗? Comparable 和 Comparator 在语义上足够接近。事实证明它们在结构上有所不同,但仍然不是最好的例子......
是否存在这样一种情况:SMI 在结构上可以很好地用作功能接口,但仍然不鼓励接口名称和方法名称的语义?或者可能是 Java 文档隐含的合同?
计划扩张。仅仅因为接口现在符合 SMI 的要求并不意味着以后不需要扩展。
好吧,如果您假设总是给出该意图,那么记录意图的注释将毫无用处。
您将示例命名为 AutoCloseable
,这显然 不是 打算作为函数实现的,因为 Runnable
对于函数来说更方便带有 ()->void
签名。它的目的是 class 实现 AutoCloseable
管理外部资源,而通过 lambda 表达式实现的匿名 classes 则不会。
一个更清楚的例子是Comparable
,一个interface
不仅不打算作为lambda表达式来实现,而且使用lambda表达式也不可能正确地实现它。
未将 interface
标记为 @FunctionalInterface
的可能原因示例:
interface
具有编程语言语义,例如AutoClosable
或Iterable
(您自己的界面不太可能发生这种情况)- 预计
interface
不会有任意实现 and/or 与其说是实际实现,不如说是一个标识符,例如java.net.ProtocolFamily
或java.lang.reflect.GenericArrayType
(请注意,后者还将继承default
实现,因为getTypeName()
对于依赖于toString()
的 lambda 实现无用) 这个
实现interface
的实例应该有一个标识,例如java.net.ProtocolFamily
、java.nio.file.WatchEvent.Modifier
等。请注意,这些通常由enum
另一个例子是
java.time.chrono.Era
,它恰好只有一个abstract
方法,但是 its specification 说“Era
的实例可以使用==
运算符。”interface
旨在改变一个操作的行为,在没有 inheriting/implementing 的情况下实现interface
是没有意义的,例如java.rmi.server.Unreferenced
- 它是对classes常用操作的抽象,它应该不止这些操作,例如
java.io.Closeable
、java.io.Flushable
、java.lang.Readable
- 预期的继承是契约的一部分,并禁止 lambda 表达式实现,例如在
java.awt
中:ActiveEvent
应该由AWTEvent
实现,PrinterGraphics
由Graphics
实现,同样适用于java.awt.print.PrinterGraphics
(嘿,两个interface
s 对于完全相同的事情...),wherasjavax.print.FlavorException
应该由javax.print.PrintException
subclass 实现
- 不知道是不是各种事件监听器接口没有标上
@FunctionalInterface
是为了和其他不能是函数式接口的多方法事件监听器对称,其实事件监听器是不错的选择对于 lambda 表达式。如果您想稍后删除侦听器,则必须存储实例,但这与例如内部 class 侦听器实现。 库维护者拥有超过 200 种候选类型的大型代码库,没有资源来讨论每个
interface
是否应该注释,因此专注于成为的主要候选者在功能上下文中使用。我敢肯定,例如java.io.ObjectInputValidation
,java.lang.reflect.InvocationHandler
, jucRejectedExecutionHandler
&ThreadFactory
不会像@FunctionalInterface
那样糟糕,但我不知道是否,例如java.security.spec.ECField
是一个很好的候选人。图书馆越通用,图书馆的用户就越有可能针对他们感兴趣的特定interface
回答该问题,但是坚持要求图书馆维护者回答 [=] 是不公平的80=]所有 接口。在这种情况下,将
@FunctionalInterface
的存在看作是一条消息,表明interface
绝对旨在与 lambda 表达式一起使用,而不是将@FunctionalInterface
的不存在视为更有意义注释作为指示符,因为它不打算以这种方式使用。这与编译器处理它的方式完全一样,您可以使用 lambda 表达式实现每个抽象方法interface
,但是当存在注释时,它将 确保 您可以使用它interface
这样。
在java8中,函数式接口是只有一个抽象方法的接口,称为函数式方法,lambda表达式的参数和return类型匹配。
java.util.function
包含 JDK 使用的通用功能接口,也可供最终用户使用 。虽然它们不是 lambda 表达式可能适用的完整功能接口集,但它们提供的功能足以满足常见需求。当现有集不够时,您可以自由创建自己的功能接口。
有许多这样的接口值得被指定为功能接口,但是java.util.function
包已经为我们几乎所有的目的提供了功能接口。
例如查看以下代码。
public interface Comparable<T> {
public int compareTo(T o);
}
@FunctionalInterface
public interface ToIntFunction<T> {
int applyAsInt(T value);
}
public static void main(String[] args){
ToIntFunction<String> f = str -> Integer.parseInt(str);
Comparable<String> c = str -> Integer.parseInt(str);
}
Comparable
也可以获取一个对象并派生一些 int 类型的值,但是提供了一个更通用的专用接口 ToIntFunction
来执行此任务。 没有硬性规定所有应得的接口都应使用 @FunctionalInterface
注释,但要获得 lambda 功能的优势,接口应满足 FunctionalInterface 定义的所有标准。