我想在Java 9中使用try with resources增强,方法是将引用变量放在try with sources中,而不是整个变量声明中。我也知道,要做到这一点,我必须遵循规则:Variable used as a try-with-resources resource should be final or effectively final
。首先,我将尝试使用local,然后使用实例变量。
- 局部变量:
-我使变量final,它遵循给定的规则并编译良好:
public static void main (String[] args) throws IOException{
final FileWriter fw = new FileWriter ("test.txt");
try(fw) {
//some code
}
}
-如果我还删除了final关键字,它将再次编译为fw
被认为是有效的final-只初始化一次且从未发生变化的变量。
public static void main (String[] args) throws IOException{
FileWriter fw = new FileWriter ("test.txt");
try(fw) {
//some code
}
}
- 实例变量:
但是同样的模式也适用于实例变量吗?让我们试试。
-首先,让我们使实例变量最终,它再次遵循规则并编译良好:
public class Test {
final FileWriter fw = new FileWriter ("a.txt");
void m1() throws IOException {
try(fw ) {
//some code
}
}
}
-如果我删除最终关键字,它应该再次编译,是吗?由于我不会在任何地方更改fw
,而是只初始化一次-应该是有效的最终。不幸的是,这行不通:
public class Test {
FileWriter fileWriter = new FileWriter ("a.txt");
void m1() throws IOException {
try(fileWriter) {
//some code
}
}
}
它给我的信息是:用作资源尝试的变量应该是final或实际上是final。所以,在这一切之后,我将回到我的第一个问题。实例变量是否可以是有效的最终,或者该术语仅用于局部变量?正如我刚才所展示的,我从来没有改变一个变量(它应该被视为有效的最终(,但编译器从来没有威胁过它。
Java语言规范,第4.12.4节。final
变量,明确规定只有局部变量和参数才能有效地成为最终变量:
某些未声明为
final
的变量被视为有效的最终变量:
局部变量(其声明符具有初始值设定项(§14.4.2((是有效的最终变量,如果以下全部为真:
未声明为
final
。它从不作为赋值表达式中的左手边出现(§15.26(。(注意,包含初始值设定项的局部变量声明符是,而不是赋值表达式。(
它从不作为前缀或后缀递增或递减运算符的操作数出现(§15.14,§15.15(
声明符缺少初始值设定项的局部变量是有效的最终变量,如果以下所有条件都为真:
未声明为
final
。每当它作为赋值表达式中的左手边出现时,它肯定是未赋值的,在赋值之前也不一定是赋值的;也就是说,它在赋值表达式的右手边之后肯定是未赋值的,而不是肯定赋值的(§16(确定性赋值((。
它从不作为前缀或后缀递增或递减运算符的操作数出现。
方法、构造函数、lambda或异常参数(§8.4.1、§8.8.1、§9.4、§15.27.1、§14.20(被视为局部变量,其声明符具有初始值设定项,目的是确定它是否是有效的最终。
如果一个变量实际上是final,那么在其声明中添加
final
修饰符将不会引入任何编译时错误。相反,如果去掉final
修饰符,则在有效程序中声明为final
的局部变量或参数实际上成为最终变量或参数。