2010-10-19 37 views
27

這種比較方法:不應分配參數'foo' - 有什麼危害?

void doStuff(String val) { 
    if (val == null) { 
     val = DEFAULT_VALUE; 
    } 

    // lots of complex processing on val 
} 

...這種方法:

void doStuff(String origVal) { 
    String val = origVal; 
    if (val == null) { 
     val = DEFAULT_VALUE; 
    } 

    // lots of complex processing on val 
} 

對於前一種方法時,Eclipse發出警告 「參數 'VAL' 不應該被分配」。爲什麼?

在我看來,前者更清潔。首先,它不會迫使我想出兩個好名字val(想出一個好的足夠硬)。

(注:假設沒有在封閉類命名爲val場)

回答

33

它看起來並不像任何人在這裏所做的倔老頭的情況。

我通常不會改變參數,實際上我傾向於標記我的參數final以明確禁止它。有幾個原因:

  • 分配給一個參數可以是混淆,企圖利用它作爲一個「輸出參數」,REF:javapractices.com和清晰度是一切

  • 青睞不變性 ,這和參數值一樣。基元只是一個同樣事物的退化情況,它(通常)更容易推斷不可變變量。參考文獻,Effective Java Item 13,或javapractices.com

  • 最後(NPI),使用最終寬鬆javapractices.com。然而,它可能在參數簽名中很難看,我相信它往往會識別意外的錯誤,並強調可變變量,這通常應該是例外。大多數代碼中的大多數可變變量都有懶惰或者認爲它會對性能產生一定影響,因爲明智選擇,不可改變和名稱良好的中間計算更清晰,更易於閱讀和驗證,並且可以針對性能進行乾淨優化沒有你的幫助。

我不能說智能在抽象您的具體情況,但禁止其他所有的事情,我可能會做不同的,我會贊成:

void doStuff(final String origVal) 
{ 
    final String valOrDefault = (origVal == null) ? DEFAULT_VALUE : origVal; 
    //lots of complex processing on valOrDefault 
} 

甚至(假設你不會告發在一個只有一個參數的實際方法中應用了一個空值,它必須是更復雜的東西的一部分)......另外,一般來說,接受null作爲參數的方法應該明確記錄爲這樣以強化空參數應該是例外的假設。在第二種方法中,您甚至可以使用@NonNull annotation。在計算器上

/** 
    * @param origVal string giving value, possibly null, in which case DEFAULT_VALUE is assigned 
    */ 
void doStuff(final String origVal, ...) 
{ 
    final String valOrDefault = (origVal == null) ? DEFAULT_VALUE : origVal; 
    // similar mucking about to make all the parameters behave, separate from 
    // actually operating on them... 
    ... 
    reallyDoStuff(valOrDefault,...); 
} 

private void reallyDoStuff(final String value, ...) 
{ 
    assert (value != null); 
    // do your complex processing 
} 

相關問題(和相關參數):"Using final modifier whenever applicable in Java...""final keyword in method parameters""Do you final-ize local variables and method parameters in Java"

+1

downvote?誰知道? ;-)你不喜歡什麼? – andersoj 2010-10-20 20:04:10

+3

我不明白什麼最終和輸出參數必須做對方。最後的參數仍然是可變的,可以用作輸出參數。另一方面,最終禁止將新對象分配給參數,並確保有對原始對象的引用,因此可用於輸出。我認爲final並不強調參數不是輸出參數。事實上,情況恰恰相反。我錯了嗎? – 2012-11-27 13:30:06

+0

@SebastianG如果參數是一個基元,那麼'final'就會阻止分配一個新的值(因此將它與inout混淆)。如果參數是一個參考,那麼'final'將阻止重新分配它。因此參數本身不是一個inout(java通過值傳遞引用 - http://stackoverflow.com/questions/40480/is-java-pass-by-reference)但當然你可以改變傳入和使用的任何對象輸出的副作用。 'final'關鍵字對此沒有影響。 – andersoj 2012-11-27 14:45:47

11

它有時被認爲是不好的做法,重新分配裏面方法的參數。它可能來自C/C++,在方法完成後調用doSomething(myVar)可以更改myVar。但是Java不是這種情況。

恕我直言,如果你把它作爲方法的第一件事情,這是非常好的。每個閱讀你的代碼的人都會明白髮生了什麼。儘管如此,如果深藏在代碼中,可能會引起混淆。

1

我懷疑這是一個style issue;更多的是程序員的指導,而不是實際的潛在問題。有些人可能會發現處置原始參數值會引起誤解。

6

根據我的經驗,使用null作爲默認參數的標記更多的是Python中的習慣用法。在Java中,您可以重載該方法。

void doStuff() { 
    doStuff(DEFAULT_VALUE); 
} 

void doStuff(final String val) { 
    assert (val != null); // or whatever 
    ... 
} 
6

有一個編譯器首選項,它指示參數分配的實例是否被忽略,標記爲警告或標記爲錯誤。

轉到菜單欄 - 選擇Window..Preferences,然後 在Preferences對話框的樹形控件中,選擇Java..Compiler..Errors/Warnings,然後 查看Code Style部分的「Parameter分配「設置。

alt text

相關問題