簡體   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