[英]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
在賦值之前肯定是未賦值的。
我認為解釋拒絕代碼的原因是:
這個對嗎?
“有效最終”的定義指出添加final
修飾符不應更改任何內容。 讓我們這樣做,得到一個更清晰的錯誤:
error: variable fileSize might already have been assigned
fileSize = 42;
^
因此,這與帶有try / catch的Final變量賦值完全相同(這也提供了使用第二個final變量的解決方法),即該變量出現在賦值的左側,這意味着它不一定是未賦值的。
(對於良好順序,try-catch與該問題無關:他們只是認為catch異常參數被認為是最終參數。)
“有效最終”的意圖是基於存在兩個線程,每個線程都有一個同名變量的副本 。 這兩個線程/變量的生命周期不同。 他們希望防止更改一個線程,而這需要進行一些同步和生命周期檢查。
因此,他們絕對不希望作業。 由語言設計決定。
事實上,在一個內螺紋canThrow could
使用fileSize
為仍為0捕捉其他變量設置后, fileSize
到42,我認為你考慮引發異常,以表示其他線程已經死了。
在這種情況下,您想要的是Future / FutureTask等。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.