实例变量可以有效地最终确定吗/ Java中仅局部变量有效地最终确定吗?

问题描述

我想在Java 9中使用 try-with-resources增强功能,方法是将引用变量放在try的资源中,而不是整个变量的声明中。我也知道,要做到这一点,我必须遵循规则: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. 实例变量:

但是这种相同的模式也适用于实例变量吗?试试吧。

-首先让我们将实例变量设置为 final ,该变量再次遵循规则并可以正常编译:

public class Test {
  final FileWriter fw = new FileWriter ("a.txt");

    void m1() throws IOException {
        try(fw ) {
            //some code
        }
    }
}

-如果我删除了 final 关键字,应该再次编译,对吗?由于我不会在任何地方进行fw的更改,而只能对其进行一次初始化-应该是有效的final 。不幸的是,这行不通:

public class Test {
   FileWriter fileWriter = new FileWriter ("a.txt");

    void m1() throws IOException {
        try(fileWriter) {
            //some code
        }
    }
}

它给我的信息是:用作资源尝试资源的变量应该是最终的或实际上是最终的。所以毕竟,我要回到我的第一个问题。实例变量可以有效地定为还是该术语仅用于局部变量?正如我刚刚展示的那样,我从未对变量进行过变异(应该将其有效地视为最终变量),但是编译器从未这样威胁它。

解决方法

Java Language Specification4.12.4. final Variables部分明确规定,只有局部变量和参数可以有效地定为

某些未声明为final的变量被认为是有效的最终变量

  • 一个局部变量,其声明符具有一个初始化程序(§14.4.2),如果满足以下所有条件,则有效地是最终的

    • 未声明为final

    • 在赋值表达式(§15.26)中,它永远不会出现在左侧。 (请注意,包含初始化程序的局部变量声明符是 not 赋值表达式。)

    • 它永远不会作为前缀或后缀递增或递减运算符(§15.14§15.15)的操作数出现。

  • 声明符缺少初始化程序的局部变量有效最终变量,如果满足以下所有条件:

    • 未声明为final

    • 每当它出现在赋值表达式的左侧时,它肯定是未赋值的,也没有在赋值之前确定赋值;也就是说,在赋值表达式(§16 (Definite Assignment))的右侧之后,它肯定是未赋值的,也不一定是赋值的。

    • 它永远不会作为前缀或后缀递增或递减运算符的操作数出现。

  • 方法,构造函数,lambda或异常参数§8.4.1§8.8.1§9.4§15.27.1,{{ 3}})的目的是为了确定它是否有效地为终结符,作为其声明符具有初始化程序的局部变量。

如果变量实际上是最终变量,则在其声明中添加final修饰符不会引入任何编译时错误。相反,如果删除了final修饰符,则在有效程序中声明为final的局部变量或参数将变为有效的最终变量。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...