@Retention of Java 类型检查器注解
@Retention of Java type checker annotations
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
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)
。这些注释中的 RetentionPolicy.RUNTIME
是否有任何特殊原因?
说明:Checker Framework 支持注释中的注释以实现向后兼容性。然而,使用 Java 8 中的那些只是为了避免运行时依赖性似乎是一个肮脏的 hack。
每个注释都有其用途!
javax.validation.constraints.NotNull
这个是bean validation规范定义的,用来在运行时进行非空检查,所以需要在运行时保留它来进行,比如一个form valdiation ...
@RetentionPolicy.SOURCE => 通常用于文档
@RetentionPocily.CLASS => 允许将一些信息提供给编译器而不是 JVM(例如,在编译期间执行代码生成)
@RetentionPolicy.RUNTIME => 允许在 JVM 级别(因此在运行时)检索注释信息。
此致,
洛伊克
这是个好问题。
为了在编译时进行静态检查,CLASS
保留就足够了。请注意,SOURCE
保留是不够的,因为需要单独编译:当对 class 进行类型检查时,编译器需要读取其使用的库上的注释,并且单独编译的库可用于编译器仅作为 class 个文件。
注释设计者使用 RUNTIME
保留来允许工具执行 运行 时间操作。这可能包括检查注释(如 assert 语句)、动态加载代码的类型检查、强制转换和 instanceof
操作的检查、更精确地解析反射等等。如今这样的工具并不多,但注释设计者希望将来能容纳它们。
您曾说过 @Retention(RetentionPolicy.CLASS)
,"the code does not have any runtime dependencies on the respective library." 实际上 @Retention(RetentionPolicy.RUNTIME)
也是如此!看到这个堆栈溢出问题:
Why doesn't a missing annotation cause a ClassNotFoundException at runtime?.
总而言之,在 运行 时,使用 CLASS
留存成本 space 可以忽略不计,可以在未来实现更多潜在用途,并且不会引入 运行-时间依赖性。
对于 Checker Framework,它提供 运行 次测试,例如 isRegex(String)
。如果您的代码使用此类方法,您的代码将依赖于 Checker Framework 运行time 库(它比整个 Checker Framework 本身更小并且具有更宽松的许可)。
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
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)
。这些注释中的 RetentionPolicy.RUNTIME
是否有任何特殊原因?
说明:Checker Framework 支持注释中的注释以实现向后兼容性。然而,使用 Java 8 中的那些只是为了避免运行时依赖性似乎是一个肮脏的 hack。
每个注释都有其用途!
javax.validation.constraints.NotNull
这个是bean validation规范定义的,用来在运行时进行非空检查,所以需要在运行时保留它来进行,比如一个form valdiation ...
@RetentionPolicy.SOURCE => 通常用于文档 @RetentionPocily.CLASS => 允许将一些信息提供给编译器而不是 JVM(例如,在编译期间执行代码生成) @RetentionPolicy.RUNTIME => 允许在 JVM 级别(因此在运行时)检索注释信息。
此致,
洛伊克
这是个好问题。
为了在编译时进行静态检查,CLASS
保留就足够了。请注意,SOURCE
保留是不够的,因为需要单独编译:当对 class 进行类型检查时,编译器需要读取其使用的库上的注释,并且单独编译的库可用于编译器仅作为 class 个文件。
注释设计者使用 RUNTIME
保留来允许工具执行 运行 时间操作。这可能包括检查注释(如 assert 语句)、动态加载代码的类型检查、强制转换和 instanceof
操作的检查、更精确地解析反射等等。如今这样的工具并不多,但注释设计者希望将来能容纳它们。
您曾说过 @Retention(RetentionPolicy.CLASS)
,"the code does not have any runtime dependencies on the respective library." 实际上 @Retention(RetentionPolicy.RUNTIME)
也是如此!看到这个堆栈溢出问题:
Why doesn't a missing annotation cause a ClassNotFoundException at runtime?.
总而言之,在 运行 时,使用 CLASS
留存成本 space 可以忽略不计,可以在未来实现更多潜在用途,并且不会引入 运行-时间依赖性。
对于 Checker Framework,它提供 运行 次测试,例如 isRegex(String)
。如果您的代码使用此类方法,您的代码将依赖于 Checker Framework 运行time 库(它比整个 Checker Framework 本身更小并且具有更宽松的许可)。