@Retention Java 类型检查器注解 [英] @Retention of Java type checker annotations
问题描述
Java 8 类型注释 (JSR 308) 允许类型检查器执行静态代码分析.例如,检查器框架可以通过@NonNull<检查可能的nullness/code> 注释.
The Java 8 type annotations (JSR 308) allow type checkers to perform static code analysis. For example, The Checker Framework can check for possible nullness via @NonNull
annotations.
各种项目定义了自己的NonNull注解,例如:
Various projects define their own NonNull annotations, for example:
org.checkerframework.checker.nullness.qual.NonNull
edu.umd.cs.findbugs.annotations.NonNull
javax.annotation.Nonnull
javax.validation.constraints.NotNull
lombok.NonNull
org.eclipse.jdt.annotation.NonNull
- 等.(请参阅检查器框架手册,第 3.7 节)
对于此类注释,我希望 @interface
具有 @Retention(RetentionPolicy.CLASS)
,因为它们通常在运行时不需要.最重要的是,代码对各自的库没有任何运行时依赖性.
For such annotations, I would expect the @interface
to have @Retention(RetentionPolicy.CLASS)
, because they are usually not needed at runtime. Most importantly, the code does not have any runtime dependencies on the respective library.
虽然 org.eclipse.jdt.annotation.NonNull
遵循这种方法,大多数其他 NonNull 注释,如 javax.annotation.Nonnull
(JSR 305) 和 org.checkerframework.checker.nullness.qual.NonNull
本身,有 @Retention(RetentionPolicy.RUNTIME)
.这些注释中的 RetentionPolicy.RUNTIME
有什么特别的原因吗?
While org.eclipse.jdt.annotation.NonNull
follows this approach, most other NonNull annotations, like javax.annotation.Nonnull
(JSR 305) and org.checkerframework.checker.nullness.qual.NonNull
itself, have @Retention(RetentionPolicy.RUNTIME)
. Is there any particular reason for the RetentionPolicy.RUNTIME
in these annotations?
澄清:Checker 框架支持注释中的注释以实现向后兼容性.然而,在 Java 8 中使用那些只是为了避免运行时依赖似乎是一个肮脏的黑客.
Clarification: The Checker Framework supports annotations in comments for backward compatibility. However, using those in Java 8 just to avoid runtime dependencies seems like a dirty hack.
推荐答案
这是个好问题.
为了在编译时进行静态检查,CLASS
保留就足够了.请注意,SOURCE
保留是不够的,因为单独编译:在对类进行类型检查时,编译器需要读取它使用的库上的注释,并且单独编译的库可用于编译器仅作为类文件.
For the purpose of static checking at compile time, CLASS
retention would be sufficient. Note that SOURCE
retention would not be sufficient, because of separate compilation: when type-checking a class, the compiler needs to read the annotations on libraries that it uses, and separately-compiled libraries are available to the compiler only as class files.
注释设计者使用 RUNTIME
保留来允许工具执行运行时操作.这可能包括检查注释(如断言语句)、动态加载代码的类型检查、强制转换和 instanceof
操作的检查、更精确地解析反射等等.现在这样的工具并不多,但注释设计者希望在未来适应它们.
The annotation designers used RUNTIME
retention to permit tools to perform run-time operations. This could include checking the annotations (like an assert statement), type-checking of dynamically-loaded code, checking of casts and instanceof
operations, resolving reflection more precisely, and more. Not many such tools exist today, but the annotation designers wanted to accommodate them in the future.
您使用 @Retention(RetentionPolicy.CLASS)
表示,代码对相应库没有任何运行时依赖项."这对于 @Retention(RetentionPolicy.RUNTIME)
也是如此!请参阅此堆栈溢出问题:为什么缺少注释在运行时不会导致 ClassNotFoundException? .
You remarked that with @Retention(RetentionPolicy.CLASS)
, "the code does not have any runtime dependencies on the respective library." This is actually true with @Retention(RetentionPolicy.RUNTIME)
, too! See this Stack Overflow question:
Why doesn't a missing annotation cause a ClassNotFoundException at runtime? .
总而言之,使用 CLASS
保留在运行时消耗的空间量可以忽略不计,可以在未来实现更多潜在用途,并且不会引入运行时依赖性.
In summary, using CLASS
retention costs a negligible amount of space at run time, enables more potential uses in the future, and does not introduce a run-time dependency.
就 Checker 框架而言,它提供运行时测试,例如 isRegex(String)
.如果您的代码使用此类方法,则您的代码将依赖于 Checker Framework 运行时库(该库比整个 Checker Framework 本身小且具有更宽松的许可).
In the case of the Checker Framework, it offers run-time tests such as isRegex(String)
. If your code uses such methods, your code will be dependent on the Checker Framework runtime library (which is smaller than the entire Checker Framework itself and has a more permissive license).
这篇关于@Retention Java 类型检查器注解的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!