java的原因是什么。lang.annotation。保持
我很清楚RetentionPolicy
的含义,知道它们做什么,什么时候做。对于我自己的注释,我确切地知道它们是在运行时、类文件中还是仅仅用于编译。然而,对于库中定义的任何注释,您永远无法确定
例如,javax.annotation.Generated
用于标记生成的代码,但很少有用。由于处理字节码的工具比处理源代码的工具多得多,因此信息在使用之前就消失了
由于运行时don't throwClassNotFoundException
缺少注释(与缺少接口不同),使用RetentionPolicy.RUNTIME
似乎不会造成伤害。还是我错了
还是说节省几个字节是使用不同Retention
的原因?对我来说,这似乎造成了太多的问题,不值得这么做。我错过了什么
# 1 楼答案
Java注释的灵感出现在2002年之前,大约是从Java1.3过渡到Java1.4。当时的高规格桌面是2.5GHz左右的奔腾4或2GHz左右的Athlon XP+,RAM为256或512MB。例如一篇评论
问题是如何存储和检索有关代码的元数据。典型的解决方案是使用未进行类型检查或未直接链接到源代码的XML文件。其他人已经非正式地为代码生成工具扩展了JavaDoc(源代码和扩展API出现在JDK中)。解决方案Annotations是一个扩展Javadoc和JLS类规范的hack(非常好的hack)
很明显,最初的作者担心性能(在2002年,Java仍然相对缓慢,反射非常缓慢,Java运行时占用了大量内存;有些事情永远不会改变)。这是对JSR-175的介绍:
他们解决问题的方法是将问题分为三个用例:
这使得(当时)上述定义的“特定工具”和“通用工具”的重要用例能够在不给运行时造成负担的情况下完成它们的工作;对于这些工具,注释可以是源代码,也可以是类。只有运行时需要的注释(从上面可以看出,这被认为是少数用例)才会加载并保留在JVM中
因此,是的,保留策略是为了节省字节和运行时开销。虽然这看起来很奇怪,但2002年是一个不同的世界,内存和性能是非常现实的问题。现在我们有了10倍的性能和内存,您可以放心地使用运行时保留
# 2 楼答案
注释的主要目的是为编译单元携带元数据。大多数标准注释都清楚地表达了有助于代码开发和编译的元信息(通过指定可由IDE或编译器验证的属性)
注释不是为修改语言的运行时语义而设计的。因此,注释在运行时是否可用本身不会改变执行。(当然,如果您主动地使用元信息来调整您的实现行为,那么一切都是可能的。)
如果在库jar中的某个地方,注释被标记为
RetentionPolicy.RUNTIME
,那么很明显,从运行时访问注释(使用反射)对以后的用户很有用如果同时注释的实现来自另一个库,那么这种期望要么是没有保证的,要么是由于该注释的特定目的,可能只对某些用例有用。(当然,仅仅为不同的保留设置构建不同的jar版本是不合适的。)
因此,如果开发人员将注释标记为
RetentionPolicy.RUNTIME
,那么在期望运行时访问的地方有一个明确的用例。注释实现是否使用相同的jar或不同的jar可能独立于用例(例如,基于其他结构化标准)。在任何情况下,如果您打算从这个用例中获益,那么在您的类路径中就会有这个注释库(因为您可能还需要其他组件),一切都很好。如果您不应用于此用例,那么您将不会受到缺少注释实现的影响改写你的问题:
使用
RUNTIME
保留不会对程序造成任何伤害,只会使(字节码)可执行文件中的死信息变得混乱。只有在预期(并且认为有用)元信息的运行时使用时才使用RUNTIME
保留增加了代码质量(在可维护性和可理解性方面)# 3 楼答案
看看源代码编辑器,Android Studio源自JetBrains和许多其他IDE,需要处理源代码,它提供了所有伟大的编辑体验,只是因为编译时注释
在编辑类(尚未编译)时,编辑器可以存储和处理注释
例如:
@SuppressWarnings
让我们来抑制警告,否则怎么做?C#允许您定义#PRAGMA
,#IF
,某种条件编译。编译输出中不存储任何条件编译信息@Override
允许Java编译器检查基类是否有要重写的方法,如果您使用错误的参数定义新方法,Java编译器将使用重载的新方法编译类,但在存在@Override
的情况下,Java编译器将给您一个错误,即签名与重写方法不正确匹配@GeneratedCode
允许IDE跳过使用“查找和替换”搜索时显示的类和成员,并且它允许您仅对代码而不是生成的代码操作IDE。你有没有看过R.*
Android中的资源,这些生成的类隐藏在Android Studio中,但它们确实提供了有用的代码完成列表类似地,许多这样的注释允许您进行代码分析、编写单元测试等,并在编译之前对其进行更多的工作
这里有更多内容
许多ORM框架使用编译时注释并生成有用的额外类,用于类型化查询和其他帮助器类,以创建表和维护模式
结论
在上面所示的示例中,很明显,所有三个和许多这样的注释都会添加很多字节,而这些字节在运行时是完全无用的
Java有两种选择,一种是使用基于c语言中使用的
#IF
etc指令添加某种编译时注释。这将需要新的语法和新的编辑经验等,另一个是创建Retention
。在不破坏语法的情况下创建Retention
是一个不错的举动