2016-08-16 60 views
2

Java 8类型注释(JSR 308)允许类型检查器执行静态代码分析。例如,The Checker Framework可以通过@NonNull注释来检查可能的无效@ Java类型检查器注释的保留

各项目定义他们自己的非空注解,例如:

  • 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虽然如下这种方法中,大多数其它非空注解,像javax.annotation.Nonnull(JSR 305)和org.checkerframework.checker.nullness.qual.NonNull本身,有@Retention(RetentionPolicy.RUNTIME)。在这些注释中是否有任何特别原因RetentionPolicy.RUNTIME


说明:Checker Framework支持注释中的注释以实现向后兼容。但是,仅仅为了避免运行时依赖而在Java 8中使用它们看起来就像是肮脏的黑客攻击。

回答

3

这是一个很好的问题。

为了在编译时进行静态检查,CLASS保留就足够了。请注意,由于单独编译,SOURCE保留是不够的:当对类进行类型检查时,编译器需要读取它使用的库的注释,并且单独编译的库仅作为类文件提供给编译器。

注释设计师使用RUNTIME保留允许工具执行运行时操作。这可能包括检查注释(如assert语句),动态加载代码的类型检查,检查转换和操作,更精确地解析反射等等。目前这种工具并不多,但注释设计师希望在将来适应这些工具。

你说@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框架本身小)。

+0

mocking带有mockito(2.2.0版)的带注释的类的相关注意事项: While RetentionPolicy。 RUNTIME意味着二进制文件中存在的注释不必在运行时可用,https://bugs.openjdk.java.net/browse/JDK-8152174在嘲笑注释类时会在Java 8中导致NullPointerException,注释在类路径中不可用。 –

1

每个注释都有它的目的!

javax.validation.constraints.NotNull 

这那些由豆验证规范定义,用于执行运行时非空校验,所以还需要在运行时被保持来执行,例如,一个表格valdiation ...

@ RetentionPolicy.SOURCE =>通常用于文档 @ RetentionPocily.CLASS =>允许向编译器提供一些信息,但不允许JVM(例如,在编译期间执行代码生成) @ RetentionPolicy.RUNTIME =>允许在JVM级别检索注释信息(所以在运行时)。

问候,

卢瓦克

+0

是的'javax.validation.constraints.NotNull'具有运行时目的。 但是'javax.annotation.Nonnull'和'org.checkerframework.checker.nullness.qual.NonNull'没有运行时目的IMO。 –

+1

对于您的问题,没有全局的答案,取决于注释的创建者来定义它是否需要在运行时保留。 请参阅此SOW主题的一些提示:http://stackoverflow.com/questions/14810030/javax-annotation-nonnull-vs-assert – loicmathieu