Java @functionanterface如何影响JVM';什么是运行时行为?

Java @functionanterface如何影响JVM';什么是运行时行为?,java,annotations,java-8,Java,Annotations,Java 8,我最初的问题完全是重复的;也就是说,为什么该接口具有运行时保留策略 但我完全不满意被接受的答案,原因有两个: 这个接口是@Documented的事实(我相信)与此无关(尽管@Documented为什么有运行时保留策略对我来说也是个谜) 尽管在Java 8之前的Java中存在许多“可能”的功能接口(如答案所述,还有Runnable等),但这并不妨碍它们被用作“替代品”(例如,如果只需在路径上进行筛选,则可以很好地使用DirectoryStream.Filter作为谓词的替代品) 但是,它仍然有

我最初的问题完全是重复的;也就是说,为什么该接口具有运行时保留策略

但我完全不满意被接受的答案,原因有两个:

  • 这个接口是
    @Documented
    的事实(我相信)与此无关(尽管
    @Documented
    为什么有运行时保留策略对我来说也是个谜)
  • 尽管在Java 8之前的Java中存在许多“可能”的功能接口(如答案所述,还有
    Runnable
    等),但这并不妨碍它们被用作“替代品”(例如,如果只需在
    路径
    上进行筛选,则可以很好地使用
    DirectoryStream.Filter
    作为
    谓词
    的替代品)

但是,它仍然有这种保留。这意味着它必须以某种方式影响JVM的行为。如何影响?

对带有保留策略运行时的注释的唯一要求是

注释将由编译器记录在类文件中,并在运行时由VM保留,因此可以反射地读取它们。()

现在,这对运行时行为有一些影响,因为类加载器必须加载这些注释,并且VM必须将这些注释保留在内存中以进行反射访问(例如由第三方库进行)

但是,不要求VM对此类注释进行操作。

我发现了核心libs dev邮件列表,其中讨论了
@functional interface
注释的保留。这里提到的要点是允许第三方工具使用此信息进行代码分析/验证,并允许非Java JVM语言使其lambda正确映射到功能接口。一些摘录:

乔·达西(功能界面的原始提交人):

我们有意使此批注具有运行时保留 允许在运行时将其查询到各种工具等

布莱恩·戈茨

Java以外的语言有一个好处,可以将其用作确定接口是否适合传递给SAM转换机制的方法。其他语言也可以使用JDK对lambda转换的支持


因此,JVM本身似乎没有使用它,这只是第三方工具的一种附加可能性。使注释运行时可见的成本不高,因此似乎没有充分的理由不这样做。

这是一个非常奇怪的结论,即保留策略
运行时
意味着它对JV有影响因为您已经知道可以用lambda表达式实现函数接口,即使它们没有注释(我想您知道),完全可选的东西应该在JVM行为上有什么样的变化?@Holger这正是我想知道的,因此我提出了这个问题。但最终,它似乎没有什么区别……实际上,使注释运行时可见可以降低成本。字节码表示是相同的,只有属性名从
Ru更改ntimeInvisibleAnnotations
RuntimeVisibleAnnotations
,因此每个类文件至少要保存两个字节。考虑到您可能有其他运行时可见的注释,而不可见的注释非常少见,保存可能更高,因为这样可以避免在类文件中同时存在两个属性名。@Holg呃,虽然它可能会稍微减小类文件的大小,但是当您请求
class.getAnnotations()时,它会增加运行时的成本,因为运行时可见的注释会变成java对象
。如果您提出请求,则有关
@functionanterface
的信息将一直保留在内存中,直到类被卸载,即使您实际查找了其他注释。但是,考虑到加载的类中只有一小部分使用
@functionanterface
进行注释,这并不是很大的成本。