在try-with-resources中声明的变量注释?

时间:2017-08-02 15:24:11

标签: java java-8 annotations java-7 try-with-resources

只是想知道哪些注释可以用于 try-with-resources 语句中声明的变量,这是根据语法允许的。语言规范(Java 7)中的 14.20.3 部分读取,

  

TryWithResourcesStatement:
  try ResourceSpecification Block Catches opt 最后 opt

     

ResourceSpecification:
  (资源; opt )

     

资源:
  资源;资源

     

资源:
   VariableModifiers opt 输入VariableDeclaratorId = Expression

VariableModifiers 扩展为( 14.4 部分),

  

VariableModifiers:
  VariableModifier
  VariableModifiers VariableModifier

     

VariableModifier:其中之一   注释 final

你去: VariableModifier 可以有 Annotation 。嗯,这基本上意味着,我们可以这样写:

try( @SomeAnnotation SomeType obj = createSomeType() ) { 
  //some code
}

所以我的问题是:在 try-with-resources 中可以使用的注释和注释类型以及实现什么样的行为?任何创新的想法?有人用过吗?

2 个答案:

答案 0 :(得分:14)

不是在Java 7中,但我怀疑你标记了这个java-7只是因为那是引入try-with-resources的版本,你仍然对Java 7之外的可能用途感兴趣(我认为对于Java> = 8),这个问题非常有趣。

我认为没有什么特别的东西可以绑定资源和注释,它不是语法中的特殊情况;在这方面,这些变量(在try-with-resources语句中声明)与其他局部变量相同,语法也允许注释:

  • Java 7引入了try-with-resources语句,您可以在其中声明将获得special treatment的变量
  • 语法一直在Java 5上允许注释局部变量声明,当时引入了注释(但我们不得不等待Java 6获取可用于注释处理的API)
  • 但即使使用Java 7,注释处理器也可以not possible访问本地变量的注释。关于局部变量的唯一注释是"可用"是@SuppressWarnings但是那个被编译器本身特别对待,没有办法让你加入这个。
  • Java 8引入了一种新的注释上下文"声明上下文",现在有"类型上下文" ,现在是一个注释{{1可以是Target

所以答案(使用Java 8)与局部变量上的任何注释相同

(关于Java 8" type annotations&#34的一些琐事;)

...这就是它变得有趣的地方:注释任何类型的使用

  

注释可能出现的语法位置被拆分为声明上下文,其中注释适用于声明,   和类型上下文,其中注释适用于声明和表达式中使用的类型。

此类注释不会在运行时保留,但可以在编译时用于各种"检查"。请参阅checker framework,该JSR-308是基于为same author完成的工作而构建的(如果我理解正确,则由"type annotations"完成)。

非常快,因为它很有趣,现在我们可以这样做:

ElementType.TYPE_USE

此类according to the JLS的示例:

  

Checker Framework提供了一些类型注释,可以使库和应用程序开发人员受益,例如:
  @NonNull Object @Nullable [] array; // Nullable array of non-null objects @Nullable Object @NonNull [] array; // Non-null array of nullable objects @Foo List<@Foo Integer> doSomething(@Foo Integer @Foo [] arrayOfIntegers, @Foo long x) { arrayOfIntegers[0] = (@Foo int) x; return Arrays.asList(arrayOfIntegers); } - 编译器可以确定代码路径可能接收空值的情况,而无需调试NullPointerException。
  @NonNull - 编译器将标记任何更改对象的尝试。这类似于Collections.unmodifiableList,但更通用并在编译时验证   @ReadOnly - 提供编译时验证,即用作正则表达式的String是格式正确的正则表达式。
  @Regex@Tainted - 不应同时使用的标识类型的数据,例如系统命令中使用的远程用户输入或日志流中的敏感信息。
  @Untainted - 度量单位确保正确使用和比较用于测量对象的数字,或者已经过正确的单位转换。

但是,如果在try-with-resources语句的上下文中特别有用(我的意思是,不得多于或少于其他任何地方)。

回到问题:在try-with-resources语句中声明时,是否有用于局部变量的注释特别有趣?

我认为在这种情况下,应用程序基本上仅限于编译时检查,因为这样的注释将在局部变量或类型使用上,并且在运行时都不可用(或不是真的):

所以,我可以想到一个特殊的&#34;使用,但我甚至不确定它是否会非常有用,因为可能有其他方法可以实现此目的:对于您在try-with-resources语句中声明的某些特定类型的资源,您可能需要确保资源在关闭之前被完全消耗(我已经看到类似于HTTP客户端库的内容以及读取标题的API部分 - 无法记住细节)

@m

这个注释将具有目标/* Say getResponse() taps into a third-party library that has a quirk: * a response object must be consumed entirely before being closed. */ try(@MustConsumeEntirely Stream<String> lines = getResponse()) { lines.findFirst().ifPresent(System.out::println); /* The stream is not entirely consumed (unless it is only 1 line but there is no way to tell). * A smart checker could catch this and issue a warning. */ } (因此不需要新的Java 8注释类型,但需要java 8可以处理),并且检查器应该验证变量是否在try-中有效声明with-resources语句(编译器无法阻止在任何本地变量上使用它),然后分析源树以确定是否根据需要使用资源。
以100%正确的方式实现这样的检查器可能是不可能的,但在纸面上看起来可能会检查一些已知的坏模式,并且当目标变量在try-with中声明时,它通常是有意义的。资源声明。

另一个想法(仍然是变量而不是类型使用),也是非常低的用途:ElementType.LOCAL_VARIABLE,如果你想控制变量没有传递给另一个方法,因为(出于类似于上面的原因)你希望能够控制发生在后面的对象上的所有事情(例如,如前面的想法),如果传递变量则更难实现。

为了说明这样的事情是模糊的,fails框架要求你遵循他们的嵌入式DSL&#34;在某个区块内,{{3}}如果你不在。人们可以想象一个注释,以帮助检查在资源尝试块中对资源的假设框架施加的类似约束的遵从性。
并不是说这将是一个很好的设计......(我是ModelMapper的情况,DSL只是他们在java 8之前提出的一个聪明的技巧,他们现在有更好的和更安全的解决方案与lambdas)< /子>

答案 1 :(得分:6)

您可以应用于局部变量的唯一类型的注释(包括try-with-resources块的try内的变量赋值)具有@Target({ElementType.LOCAL_VARIABLE})的注释。那些在运行时(通过反射)无法访问,因此它们只能由编译器访问。

它们可能有用的例子:

  • @SuppressWarnings("unchecked") - 如果您在try(...)
  • 内有未选中的作业
  • 使用JSR 305(软件缺陷检测注释)注释,例如@Nullable@Nonnull