不在 Java 7 中,但我怀疑您标记此 java-7 只是因为那是引入 try-with-resources 的版本,并且您仍然对 Java 7 之外的可能用途感兴趣(我认为这个问题对于Java >= 8)。
我认为绑定try-with-resources和annotation没有什么特别的,在语法上不是特例;在这方面,这些变量(在 try-with-resources 语句中声明)与其他局部变量一样,并且语法也允许注释:
- Java 7 引入了 try-with-resources 语句,您可以在其中声明一个变量,该变量将获得special treatment。
- 早在 Java 5 引入注解时,该语法就已允许对局部变量声明进行注解(但我们必须等待 Java 6 才能获得用于注解处理的可用 API)
- 但即使在 Java 7 中,注解处理器访问局部变量上的注解也是 not possible。局部变量上唯一“可用”的注解是
@SuppressWarnings,但编译器本身对它进行了特殊处理,您无法挂钩。
- Java 8 在“声明上下文”之外引入了一种新的注解上下文,现在有“类型上下文”,现在注解
Target 可以是ElementType.TYPE_USE
所以答案(使用 Java 8)与对局部变量的任何注释相同。
(关于 Java 8 的新“类型注释”的一些琐事)
...这就是有趣的地方:注释任何类型的使用!
注释可能出现的句法位置被分成声明上下文,其中注释适用于声明,
和类型上下文,其中注释适用于声明和表达式中使用的类型。
此类注解不会在运行时保留,但可以在编译时用于各种“检查”。请参阅checker framework,它建立在为JSR-308 完成的工作之上(如果我理解正确,则由same author)。
很快,因为它很有趣,现在我们可以这样做了:
@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);
}
这种"type annotations"的例子:
检查器框架提供了一些类型注释,可以使库和应用程序开发人员都受益,例如:
@NonNull – 编译器可以确定代码路径可能收到空值的情况,而无需调试NullPointerException。
@ReadOnly – 编译器将标记任何更改对象的尝试。这类似于 Collections.unmodifiableList,但更通用并在编译时进行验证。
@Regex – 提供编译时验证,即打算用作正则表达式的字符串是格式正确的正则表达式。
@Tainted 和 @Untainted – 不应一起使用的数据的标识类型,例如系统命令中使用的远程用户输入,或日志流中的敏感信息。
@m – 计量单位确保数字用于测量的对象被正确使用和比较,或经过适当的单位转换。
但是,如果在 try-with-resources 语句的上下文中特别有用的话,这些都没有(我的意思是,不比其他任何地方多或少)。
回到问题:在 try-with-resources 语句中声明时,是否有用于局部变量的注释特别有趣?
我认为在这种情况下,应用程序基本上仅限于编译时检查,因为这样的注释要么在局部变量上,要么在使用的类型上,并且在运行时都不可用(或者不是真的):
所以,我可以想到一种“特殊”用途,但我什至不确定这是否非常有用,因为可能还有其他方法可以实现这一点:对于您在 try 中声明的某些特定类型的资源- with-resources 语句,您可能需要确保在关闭资源之前完全消耗资源 (我已经看到类似的 HTTP 客户端库和读取标头的 API 部分 - 不能记住细节).
/* 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. */
}
这个注解的目标是ElementType.LOCAL_VARIABLE(所以不需要新的Java 8注解类型,但需要Java 8是可处理的),检查器应该验证变量是否在try-with-中有效声明资源语句(编译器无法阻止在任何局部变量上使用它),然后分析源树以确定资源是否按要求消耗。
以 100% 正确的方式实现这样的检查器可能是不可能的,但在纸面上,它似乎可以检查一些已知的不良模式,并且当目标变量在 try-with- 中声明时,它最有意义。资源声明。
另一个想法(仍然在变量而不是类型使用),有用性也很低:@MustNotEscape,如果你想控制变量不传递给另一个方法,因为(出于类似于上面的原因)你想要能够控制后面的对象发生的所有事情(例如,如之前的想法),如果传递变量,这将更难实现。
为了说明这样的事情是隐约可能的,here is an example 一个框架希望你在某个块内遵循他们的“嵌入式 DSL”,如果你不这样做,fails。可以想象一个注释来帮助检查假设框架对 try-with-resources 块中的资源施加的类似约束的合规性。
虽然不是说这将是一个好的设计......(我以 ModelMapper 为例,DSL 只是他们在 java 8 之前提出的一个聪明的技巧,现在他们有了更好、更安全的 lambda 解决方案)