[英]Assignment of effectively final variable in try/catch statement
The following code does not compile with javac 1.8.0_144 and ecj: 以下代码无法与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;
}
I am wondering if this a bug in the compiler. 我想知道这是否是编译器中的错误。 The definition of effectively final in the JLS is:
JLS中有效最终的定义是:
Certain variables that are not declared final are instead considered effectively final:
某些未声明为final的变量实际上被认为是final:
A local variable whose declarator has an initializer (§14.4.2) is effectively final if all of the following are true:
如果满足以下所有条件,则其声明符具有初始化程序(第14.4.2节)的局部变量实际上是最终的:
It is not declared final.
它不是最终的。
It never occurs as the left hand side in an assignment expression (§15.26).
它永远不会出现在赋值表达式的左侧(第15.26节)。 (Note that the local variable declarator containing the
(请注意,包含
initializer is not an assignment expression.)初始化程序不是赋值表达式。)
It never occurs as the operand of a prefix or postfix increment or decrement operator (§15.14, §15.15).
它永远不会作为前缀或后缀递增或递减运算符的操作数出现(第15.14、15.15节)。
A local variable whose declarator lacks an initializer is effectively final if all of the following are true:
如果满足以下所有条件,则其声明符缺少初始化程序的局部变量实际上是最终的:
It is not declared final.
它不是最终的。
Whenever it occurs as the left hand side in an assignment expression, it is definitely unassigned and not definitely assigned before the assignment;
每当它出现在赋值表达式的左侧时,它肯定是未赋值的,而且在赋值之前也没有赋值; that is, it is definitely unassigned and not definitely assigned after the right hand side of the assignment expression (§16 (Definite Assignment)).
也就是说,在赋值表达式的右侧(第16节(确定赋值))之后,它肯定是未赋值的,也没有确定赋值。
It never occurs as the operand of a prefix or postfix increment or decrement operator.
它永远不会作为前缀或后缀递增或递减运算符的操作数出现。
A method, constructor, lambda, or exception parameter (§8.4.1, §8.8.1, §9.4, §15.27.1, §14.20) is treated, for the purpose of
出于以下目的,处理了方法,构造函数,lambda或异常参数(第8.4.1节,第8.8.1节,第9.4节,第15.27.1节,第14.20节)。
determining whether it is effectively final, as a local variable确定它是否最终有效,作为局部变量
whose declarator has an initializer.其声明程序具有初始化程序。
My reading is that in clause 2, the assignments in the try/catch block are allowed because fileSize
is definitely unassigned before the assignment. 我的理解是,在第2节中,允许在try / catch块中进行赋值,因为
fileSize
在赋值之前肯定是未赋值的。
I think the reasoning to explain the rejection of the code is: 我认为解释拒绝代码的原因是:
Is this correct? 这个对吗?
The definition of "Effectively final" states that adding a final
modifier should not change anything. “有效最终”的定义指出添加
final
修饰符不应更改任何内容。 Let's do that and get a clearer error: 让我们这样做,得到一个更清晰的错误:
error: variable fileSize might already have been assigned
fileSize = 42;
^
So this is the exact same case as Final variable assignment with try/catch (which also gives a workaround using a second final variable), namely the variable appears on the left of an assignment, which means it is not definitely unassigned. 因此,这与带有try / catch的Final变量赋值完全相同(这也提供了使用第二个final变量的解决方法),即该变量出现在赋值的左侧,这意味着它不一定是未赋值的。
(For good order try-catch has nothing to do with the issue: they merely argue that the catch exception parameter is considered final.) (对于良好顺序,try-catch与该问题无关:他们只是认为catch异常参数被认为是最终参数。)
The intention of being "effectively final" is founded on there being two threads with each a copy of the identically named variable. “有效最终”的意图是基于存在两个线程,每个线程都有一个同名变量的副本 。 The life times of those two threads/variables are different.
这两个线程/变量的生命周期不同。 They want to prevent change in one thread which would have needed some synchronisation and lifeliness check.
他们希望防止更改一个线程,而这需要进行一些同步和生命周期检查。
So they definitely do not want an assignment. 因此,他们绝对不希望作业。 As language design decision.
由语言设计决定。
Indeed an internal thread in canThrow could
use fileSize
being still 0 after the catch set the other variable fileSize
to 42. I think you consider a raised exception to signify the other thread is dead. 事实上,在一个内螺纹
canThrow could
使用fileSize
为仍为0捕捉其他变量设置后, fileSize
到42,我认为你考虑引发异常,以表示其他线程已经死了。
What you want in this case is a Future/FutureTask or such. 在这种情况下,您想要的是Future / FutureTask等。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.