Java 8 类型注释 (JSR 308) 允许类型检查器执行静态代码分析。例如,The Checker Framework可以通过 @NonNull
注释检查可能的nullness。
各个项目定义了自己的NonNull注解,例如:
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
- 等(参见 The Checker Framework Manual, section 3.7)
对于这样的注释,我希望 @interface
有 @Retention(RetentionPolicy.CLASS)
,因为在运行时通常不需要它们。最重要的是,代码对各自的库没有任何运行时依赖性。
同时 org.eclipse.jdt.annotation.NonNull
大多数其他 NonNull 注释都遵循这种方法,例如 javax.annotation.Nonnull
(JSR 305) 和 org.checkerframework.checker.nullness.qual.NonNull
本身,有@Retention(RetentionPolicy.RUNTIME)
.这些注释中的 RetentionPolicy.RUNTIME
是否有任何特殊原因?
说明:Checker Framework 支持注释中的注释以实现向后兼容性。然而,在 Java 8 中使用它们来避免运行时依赖似乎是一种肮脏的 hack。
最佳答案
这是个好问题。
为了在编译时进行静态检查,CLASS
保留就足够了。请注意,保留 SOURCE
是不够的,因为需要单独编译:在对类进行类型检查时,编译器需要读取它使用的库上的注释,并且单独编译的库可供编译器仅作为类文件。
注释设计者使用RUNTIME
保留来允许工具执行运行时操作。这可能包括检查注释(如 assert 语句)、动态加载代码的类型检查、强制转换和 instanceof
操作检查、更精确地解析反射等等。如今这样的工具并不多,但注释设计者希望将来能容纳它们。
您评论说,使用 @Retention(RetentionPolicy.CLASS)
,“代码对相应的库没有任何运行时依赖性。” @Retention(RetentionPolicy.RUNTIME)
实际上也是如此!看到这个堆栈溢出问题:
Why doesn't a missing annotation cause a ClassNotFoundException at runtime? .
总而言之,使用 CLASS
保留在运行时占用的空间量可以忽略不计,可以在未来实现更多潜在用途,并且不会引入运行时依赖性。
对于 Checker Framework,它提供运行时测试,例如 isRegex(String)
.如果您的代码使用此类方法,您的代码将依赖于 Checker Framework 运行时库(它比整个 Checker Framework 本身更小并且具有更宽松的许可)。
关于java - @Retention Java 类型检查器注解,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38975073/