java.lang.annotation.Retention的原因是什么?

maa*_*nus 18 java annotations retention

我很清楚它的含义RetentionPolicy并且知道它们的作用以及何时使用它们似乎是有意义的.对于我自己的注释,我确切地知道它们是在运行时,类文件中还是仅仅用于编译时需要的.但是,使用库中定义的任何注释,您可以恕我直言.

例如,javax.annotation.Generated意味着标记生成的代码,但它很少有用.由于有更多的AFAIK工具对字节码比与源工作工具工作,这些信息就会消失,可以使用之前它.

由于在运行时缺少注释不会抛出 ClassNotFoundException(不像例如,缺少接口),使用RetentionPolicy.RUNTIME似乎不会造成伤害.还是我错了?

或者节省了几个字节使用不同Retentions 的原因?对我来说,这似乎导致太多问题值得.我错过了什么?

And*_*ock 15

Java Annotations的灵感发生在2002年之前,围绕从Java 1.3到Java 1.4的过渡.当时的高规格桌面是大约2.5GHz的奔腾4或大约2GHz的Athlon XP +,RAM为256或512MB.例如这里的评论.

问题是如何存储和检索有关代码的元数据.典型的解决方案是使用未经过类型检查或直接链接到源代码的XML文件.其他人已经非正式地扩展了JavaDoc(源代码和扩展API存在于JDK中),用于代码生成工具.解决方案Annotations是扩展Javadoc和JLS Class规范的hack(非常好的hack).

很明显原作者担心性能(在2002年,Java仍然相对较慢,反射非常慢,Java运行时是一个巨大的内存耗费;有些事情永远不会改变).这是从JSR-175的介绍:

由于许多注释只能由存根生成器等开发工具使用,因此在运行时保留所有注释几乎没有意义; 这样做可能会增加运行时内存占用并损害性能.但是,有一些注释类型在运行时很有用,有些注释类型在只能访问类文件(不是源文件)的工具中很有用.因此,编译器会在类文件属性(JVMS 4.7)中存储某些注释,然后可以通过新的反射API在运行时检查其中的一些注释.

他们解决问题的方法是将问题分为三个用例:

VI.阅读注释

注释消费者可分为三组:

一个."内省检查员" - 查询自己的程序元素的运行时可见注释的程序.这些程序会将带注释的类和注释接口加载到虚拟机中.(通过运行时可见,我们指的是其保留策略  为RUNTIME的注释  .)

湾 "特定工具" - 查询任意外部程序的已知注释类型的程序.例如,存根发生器就属于这一类.这些程序将读取带注释的类而不将它们加载到虚拟机中,但会加载注释接口.

C."常规工具" - 查询任意外部程序(如编译器,文档生成器和类浏览器)的任意注释的程序.这些程序既不会将带注释的类也不会将注释接口加载到虚拟机中.据说这些节目"按照公平原则"运作.

这允许(当时)上面定义的"特定工具"和"通用工​​具"的重要用例在不对运行时造成负担的情况下完成它们的工作; 对于这些工具,注释可以是SOURCE或CLASS.只有在运行时需要的注释(从上面,很明显这被认为是少数用例)将被加载并保留在JVM中.

所以,是的,保留策略已经到位,以节省字节和运行时开销.虽然现在看起来很古怪,但2002年是一个不同的世界,记忆和表现是非常真实的问题.现在我们有10倍的性能和内存,您可以安全地使用RUNTIME保留而无需担心.


rpy*_*rpy 1

注释的主要目的是携带编译单元的元数据。大多数标准注释都清楚地表达了有助于代码开发和编译的元信息(通过指定可由 IDE 或编译器验证的属性)。

注释并不是为了修改语言的运行时语义而设计的。因此,注释在运行时是否可用本身不会改变执行。(当然,如果您积极使用元信息来调整您的实现行为,那么一切皆有可能。)

如果在库 jar 中,某处标记了注释,因为RetentionPolicy.RUNTIME显然期望从运行时访问注释(使用反射)对以后的用户有用。
如果同时注释的实现来自另一个库,那么这种期望要么没有保证,要么是由于该注释的特定目的可能只对某些用例有帮助。(仅仅针对不同的保留设置构建不同的 jar 版本肯定是不合适的。)

因此,如果开发人员在标记注释时RetentionPolicy.RUNTIME考虑到需要运行时访问的明确用例。然后,注释实现是否提供相同的 jar 或不同的 jar 可能独立于用例(例如,基于其他结构化标准)。无论如何,如果您打算从这个用例中受益,您将在类路径中拥有这个注释库(因为您可能还需要其他组件),一切都很好。如果您不应用于此用例,那么您不会受到缺少注释实现的影响。

重新表述你的问题:

除了用死信息弄乱(字节码)可执行文件之外,使用RUNTIME保留不会对程序造成任何损害。仅在预期使用元信息的运行时(并认为有用)时才使用RUNTIME保留可以提高代码质量(在可维护性和可理解性方面)。