Naw*_*waz 20 java annotations java-7 java-8 try-with-resources
只是想知道哪些注释可以用于在try-with-resources语句中声明的变量,这是根据其语法允许的.语言规范(Java 7)的第14.20.3节内容如下:
TryWithResourcesStatement:
tryResourceSpecification Block Catches opt最后选择ResourceSpecification:
(资源;选择)资源:
资源;资源资源:
VariableModifiers opt类型VariableDeclaratorId=表达式
而VariableModifiers扩展为(第14.4节),
VariableModifiers:
VariableModifier
VariableModifiers VariableModifierVariableModifier:
Annotation之一final
你去:VariableModifier可以有注释.嗯,这基本上意味着,我们可以这样写:
try( @SomeAnnotation SomeType obj = createSomeType() ) {
//some code
}
Run Code Online (Sandbox Code Playgroud)
所以我的问题是:如何以及什么样的注释可以用于资源尝试并实现什么样的行为?任何创新的想法?有人用过它们吗?
Hug*_* M. 15
不是在Java 7中,但我怀疑你标记这java-7只是因为那是引入try-with-resources的版本,你仍然对Java 7之外的可能用途感兴趣(我认为这个问题对于Java> = 8非常有趣).
我认为没有什么特别的东西可以绑定资源和注释尝试,它不是语法中的特殊情况; 在这方面,这些变量(在try-with-resources语句中声明)与其他局部变量相同,语法也允许注释:
@SuppressWarnings但是编译器本身特别处理了这个注释,没有办法让你勾选它.Target可以是ElementType.TYPE_USE所以答案(使用Java 8)与局部变量的任何注释相同.
(关于Java 8的新"类型注释"的一些琐事)
......这就是它变得有趣的地方:注释任何类型的用途!
注释可能出现的语法位置被拆分为声明上下文,其中注释适用于声明,类型上下文,其中注释适用于声明和表达式中使用的类型.
这样的注释不会在运行时保留,但可以在编译时用于各种"检查".请参阅checker框架,它构建于JSR-308的工作之上(如果我理解正确的话,由同一作者完成).
非常快,因为它很有趣,现在我们可以这样做:
@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);
}
Run Code Online (Sandbox Code Playgroud)
这种"类型注释"的例子:
Checker Framework提供了一些可以使库和应用程序开发人员受益的类型注释,例如:
@NonNull- 编译器可以确定代码路径可能接收空值的情况,而无需调试NullPointerException.
@ReadOnly- 编译器将标记任何更改对象的尝试.这类似于Collections.unmodifiableList,但更通用并在编译时验证.
@Regex- 提供编译时验证,即用作正则表达式的String是格式正确的正则表达式.
@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. */
}
Run Code Online (Sandbox Code Playgroud)
这个注释会有目标ElementType.LOCAL_VARIABLE(因此不需要新的Java 8注释类型,但需要java 8可以处理),并且检查器应该验证变量是否在try-with-resources语句中有效声明(编译器无法阻止从在任何本地变量上使用它,然后分析源树以确定是否按需要使用资源.
以100%正确的方式实现这样的检查器可能是不可能的,但在纸面上看起来可能会检查一些已知的坏模式,并且当目标变量在try-with中声明时,它将是有意义的.资源声明.
另一个想法(仍然是变量而不是类型使用),也是非常低的有用性:@MustNotEscape如果你想控制变量没有被传递给另一个方法,因为(出于与上面类似的原因)你想要能够控制发生的一切对于后面的对象(例如,如在先前的想法中),并且如果变量被传递则将更难以实现.
为了说明这样的事情是模糊的,这里有一个框架的例子,它希望你在某个块内跟随它们的"嵌入式DSL",如果你不这样做就会失败.可以想象一个注释,以帮助检查对资源尝试块内的资源的假设框架施加的类似约束的遵从性.
不是说这将是一个很好的设计...(我在ModelMapper的情况下,DSL只是他们在java 8之前提出的一个聪明的技巧,他们现在有更好和更安全的lambdas解决方案)
| 归档时间: |
|
| 查看次数: |
1001 次 |
| 最近记录: |