2012-11-28 74 views
49

因爲我認爲這是一個很好的編程習慣,所以如果它們只能寫入一次,我會將所有的變量(本地或實例)變爲final使用try/catch的最終變量賦值

然而,我注意到,當一個變量賦值可以拋出一個異常,你不能說變量決賽:

final int x; 
try { 
    x = Integer.parseInt("someinput"); 
} 
catch(NumberFormatException e) { 
    x = 42; // Compiler error: The final local variable x may already have been assigned 
} 

有沒有辦法做到這一點,而不訴諸一個臨時變量? (或者這是不是最終修改器的正確位置?)

+1

我懷疑你可以做這個沒有臨時變量。 – NPE

+8

'final int x = makeX();'絕對。 (try-catch函數) –

+2

令人震驚的是,JDK [仍然沒有'tryParse'](http://stackoverflow.com/questions/1486077/java-good-way-to-encapsulate-integer-parseint) 。 –

回答

44

一種方法是通過引入(非final)臨時變量,但是您說你不想這樣做。

另一種方法是代碼的兩個分支進入一個功能:

final int x = getValue(); 

private int getValue() { 
    try { 
    return Integer.parseInt("someinput"); 
    } 
    catch(NumberFormatException e) { 
    return 42; 
    } 
} 

這是否是實際取決於確切使用情況。總而言之,只要x是一個適當範圍的局部變量,最實用的一般方法可能是將它保留爲非0,即final

如果,另一方面,x是一個成員變量,我的建議是在初始化過程中使用非final臨時:

public class C { 
    private final int x; 
    public C() { 
    int x_val; 
    try { 
     x_val = Integer.parseInt("someinput"); 
    } 
    catch(NumberFormatException e) { 
     x_val = 42; 
    } 
    this.x = x_val; 
    } 
} 
+0

對於本地範圍,我同意你的看法,但是這通常發生在實例變量上。 – dtech

+0

我想它可能反映出一個錯誤,無法對非靜態方法getValue()進行靜態引用,所以我們假設使用靜態函數,,我可能是錯誤的private static int getValue().. @ NPE – gks

+0

If this.x是一個像Integer這樣的對象類型,那麼你需要多一點(可悲)。如果你離開x_val未聲明,編譯器會抱怨它可能沒有被初始化。如果catch塊的後退爲空,則需要將其初始化爲null,併爲了清楚起見(爲了清楚起見,在catch中冗餘地分配null)或者有一個空的catch。 –

2

不,它是不正確的地方,想象你得到更多的然後在你的try和catch塊中使用1個語句,第一個語句表示:x = 42。在其他一些語句之後,try塊失敗,並進入catch塊,其中你的say x = 30.現在你定義了x兩次。

+9

編譯器足夠聰明,可以知道哪些語句拋出了哪些異常。這在所有情況下都是不可能的,但就像編譯器可以在某些情況下告訴你關於死代碼等等,它應該能夠弄清楚最終是否會起作用。 – Stefan

+0

爲了支持@Stefan說的話,Clang在編譯Swift時能夠解決這個問題。 –