只是想知道在try-with-resources语句中声明的变量可以使用什么批注,按其语法是允许的。语言规范(Java 7)中的14.20.3部分内容如下:
TryWithResourcesStatement:
try
ResourceSpecification Block Catchesopt FinallyoptResourceSpecification:
(
Resources;
opt)
Resources:
Resource Resource;
ResourcesResource:
VariableModifiersopt Type VariableDeclaratorId=
Expression
并且VariableModifiers扩展为(第14.4节),
VariableModifiers:
VariableModifier
VariableModifiers VariableModifierVariableModifier: one of
Annotationfinal
到此为止:VariableModifier可以具有注释。好吧,这基本上意味着,我们可以这样写:
try( @SomeAnnotation SomeType obj = createSomeType() ) {
//some code
}
所以我的问题是:尝试资源中可以怎样使用哪种注释以及实现哪种行为?有什么创新想法吗?有人用过吗?
最佳答案
不是在Java 7中,而是我怀疑您标记了java-7
只是因为这是引入try-with-resources的版本,并且您仍然对Java 7以外的可能用途感兴趣(我认为这个问题对于Java> = 8非常有趣) 。
我认为绑定(bind)try-with-resources和批注没有什么特别的,在语法上不是特殊的情况。在这方面,这些变量(在try-with-resources语句中声明)与其他局部变量相同,并且语法也允许注释:
@SuppressWarnings
,但编译器本身已对其进行了特殊处理,因此您无法将其挂钩。 Target
可以是ElementType.TYPE_USE
因此,答案(对于Java 8)为,与对本地变量的任何注释相同。
(有关Java 8的新“类型注释”的一些琐事)
...,这就是变得有趣的地方:使用注释任何类型!
The syntactic locations where annotations may appear are split into declaration contexts , where annotations apply to declarations, and type contexts, where annotations apply to types used in declarations and expressions.
此类注释不会在运行时保留,但可以在编译时用于各种“检查”。请参阅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"的示例:
The Checker Framework provides a few Type Annotations that could benefit both library and application developers, such as:
@NonNull
– The compiler can determine cases where a code path might receive a null value, without ever having to debug a NullPointerException.
@ReadOnly
– The compiler will flag any attempt to change the object. This is similar to Collections.unmodifiableList, but more general and verified at compile time.
@Regex
– Provides compile-time verification that a String intended to be used as a regular expression is a properly formatted regular expression.
@Tainted
and@Untainted
– Identity types of data that should not be used together, such as remote user input being used in system commands, or sensitive information in log streams.
@m
– Units of measure ensures that numbers used for measuring objects are used and compared correctly, or have undergone the proper unit conversion.
但是,如果在try-with-resources语句的上下文中特别有用,则没有一个(我的意思是,没有比任何其他地方更多或更少)。
回到问题:是否有用于局部变量的注释的方法,这些注释在try-with-resources语句中声明时会特别有趣?
我认为在这种情况下,应用程序本质上将被限制为编译时检查,因为这样的注释将在局部变量或类型使用上,并且在运行时都不可用(或实际上不可用):
二进制变量中未保留本地变量的
类型使用的
因此,我可以想到一种“特殊”用途,但是我什至不确定这是否会非常有用,因为可能还有其他方法可以实现此目的:对于在try-with-resources中声明的某些特定类型的资源语句,您可能需要确保在关闭资源之前已完全消耗该资源(我已经通过HTTP客户端库以及读取 header 的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-resources语句中有效地声明了(编译器不能阻止在任何局部变量上使用它),然后分析源树以确定是否按需使用了资源。可能不可能以100%正确的方式实现这种检查器,但是在纸上看起来可以检查一些已知的错误模式,并且当在try-with-中声明目标变量时,这在大多数情况下是有意义的资源声明。
另一个想法(仍然使用变量而不是类型使用),其实用性也很低:
@MustNotEscape
,如果您想控制不将变量传递给另一个方法,因为(出于与上述类似的原因)您希望能够控制所有发生在后面的对象上(例如,按照先前的想法),如果传递变量,则将很难完成。为了说明这种事情几乎是可能的,框架的here is an example期望您在某个块内遵循其“嵌入式DSL”,否则请访问fails。可以想象一下一种注释,以帮助检查是否有一个假设框架对“尝试使用资源”块中的资源施加的类似约束的合规性。
不过,并不是说这将是一个好的设计……(就ModelMapper而言,DSL只是他们在Java 8之前提出的一个巧妙技巧,现在他们有了使用lambda的更好,更安全的解决方案)
关于java - 在try-with-resources中声明的变量的注释?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45464920/