繁体   English   中英

在try / catch语句中有效地分配最终变量

[英]Assignment of effectively final variable in try/catch statement

以下代码无法与javac 1.8.0_144和ecj一起编译:

private LongSupplier foo() {
    long fileSize;
    try {
        fileSize = canThrow();
    } catch (IOException e) {
        fileSize = 42;
    }

    LongSupplier foo = () -> 1 + fileSize;
    return foo;
}

我想知道这是否是编译器中的错误。 JLS中有效最终的定义是:

某些未声明为final的变量实际上被认为是final:

  • 如果满足以下所有条件,则其声明符具有初始化程序(第14.4.2节)的局部变量实际上是最终的:

    • 它不是最终的。

    • 它永远不会出现在赋值表达式的左侧(第15.26节)。 (请注意,包含
      初始化程序不是赋值表达式。)

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

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

    • 它不是最终的。

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

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

  • 出于以下目的,处理了方法,构造函数,lambda或异常参数(第8.4.1节,第8.8.1节,第9.4节,第15.27.1节,第14.20节)。
    确定它是否最终有效,作为局部变量
    其声明程序具有初始化程序。

我的理解是,在第2节中,允许在try / catch块中进行赋值,因为fileSize在赋值之前肯定是未赋值的。

我认为解释拒绝代码的原因是:

  • 在try块之前,绝对未分配fileSize
  • 在fileSize = canThrow()之后,分配了fileSize(肯定吗?似乎16.1.8不在乎分配中的异常)
  • 在try块之后分配fileSize
  • 在catch块之前不一定未分配fileSize,因此在catch块中分配之前不一定未分配fileSize。
  • 因此,第4.12.4条第2款在此不适用

这个对吗?

“有效最终”的定义指出添加final修饰符不应更改任何内容。 让我们这样做,得到一个更清晰的错误:

error: variable fileSize might already have been assigned
                    fileSize = 42;
                    ^

因此,这与带有try / catch的Final变量赋值完全相同(这也提供了使用第二个final变量的解决方法),即该变量出现在赋值的左侧,这意味着它不一定是未赋值的。

(对于良好顺序,try-catch与该问题无关:他们只是认为catch异常参数被认为是最终参数。)

“有效最终”的意图是基于存在两个线程,每个线程都有一个同名变量的副本 这两个线程/变量的生命周期不同。 他们希望防止更改一个线程,而这需要进行一些同步和生命周期检查。

因此,他们绝对不希望作业。 由语言设计决定。

事实上,在一个内螺纹canThrow could使用fileSize为仍为0捕捉其他变量设置后, fileSize42,我认为你考虑引发异常,以表示其他线程已经死了。

在这种情况下,您想要的是Future / FutureTask等。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM