实例变量是否可以有效地成为最终变量/在Java中是否只有局部变量有效地成为最后变量



我想在Java 9中使用try with resources增强,方法是将引用变量放在try with sources中,而不是整个变量声明中。我也知道,要做到这一点,我必须遵循规则:Variable used as a try-with-resources resource should be final or effectively final。首先,我将尝试使用local,然后使用实例变量。

  1. 局部变量:

-我使变量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
}
}
  1. 实例变量:

但是同样的模式也适用于实例变量吗?让我们试试。

-首先,让我们使实例变量最终,它再次遵循规则并编译良好:

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的局部变量或参数实际上成为最终变量或参数。

最新更新