2009-10-07 67 views
33

我已閱讀下面的討論:在什麼情況下靜態方法是一種好的做法?

Should private helper methods be static if they can be static,並且
Should all methods be static if their class has no member variables

看來,一般人會接受靜態方法,但都有點懷疑它,有以下兩個原因:

  1. 他們很難測試。
  2. 他們違反了OO原則。 (他們 是功能,而不是方法,說 人。)

而且最能接受的靜態方法私有靜態的。但是爲什麼靜態方法完全存在,以及在什麼情況下它們是被優先採用的首要任務?

+0

這個討論也很有用:什麼時候不在Java中使用static關鍵字http://stackoverflow.com/questions/1766715/when-not-to-use-the-static-keyword-in-java – 2013-02-12 13:33:23

回答

52

靜態方法本身並不難測試。問題是其他代碼調用的靜態方法很難測試,因爲你不能替換靜態方法。

我認爲靜態方法很好,當他們是私人的,當他們是「實用」的方法 - 例如,做字符串轉義。問題出現在你使用靜態方法的時候,你希望能夠模擬出或者在測試中替換掉。工廠方法也可以使用,儘管依賴注入通常是一種更好的方法 - 再次,它部分取決於您是否希望能夠替換測試中的功能。至於不是「OO」 - 並非所有用OO語言編寫的所有內容都必須是「純粹的」OO。有時非OO路線更加實用,並導致更簡單的代碼。 Eric Lippert在這方面有一篇很棒的博客文章,很不幸我現在找不到。但是,在this post中有相關的評論。它討論的是擴展方法而不是靜態方法,但原理是一樣的。

擴展方法經常被批評 爲「不OOP不夠。」這似乎是 對我來說,把車放在馬的前面 。 OOP的目的是爲 由 隊的人寫的大型軟件項目的結構 誰不需要 知道爲了 生產各 其他工作的內部細節提供指引。 C#的目的是成爲 這種有用的編程語言,它使我們的客戶能夠在我們的平臺上高效地生產 。顯然OOP是 有用和流行,並且我們已經 因此試圖使在C#中的OOP風格的程序易於 。但是C#的目的不是「成爲OOP 語言」。我們根據 評估功能是否對我們的 客戶有用,而不是基於它們是否嚴格遵守一些抽象的 理論,這些理論是爲了使面向對象的語言成爲 。我們 高興地從oo, 功能,程序,命令, 聲明,只要我們 可以使一個有益的產品 有利於我們的客戶。

+0

非常真實,允許更簡潔的代碼,並且更容易重用。 – 2009-10-07 08:55:42

+0

謝謝。很好的解釋。所以你認爲效用方法是一個好習慣,對吧?但後來我不明白爲什麼人們會使用靜態,然後「私人」或「實用」。基本上,我使用實用方法很多。 – 2009-10-07 09:01:45

+2

嗯,它是任何時候你寫一個邏輯上與該類型相關的方法而不是該類型的一個實例。在一些地區這很常見,在其他國家很少見。 – 2009-10-07 09:19:32

1

我覺得對於靜態方法一定情況下是當你不能讓他們動態的,因爲你不能修改類

這是典型的JDK對象,以及所有來自外部庫的對象,以及原始類型

5

想一想這一刻。在面向對象的編碼,每一個函數調用實際上是這樣的:

method(object this, object arg1, object arg2)哪裏這是您呼叫的對象。所有它真的是這樣的語法糖。此外它可以讓你清楚地定義的變量的作用域,因爲你有對象變量等

靜態方法根本就沒有「這個」參數。即你傳入變量並可能返回結果。 1.)是人們避免它們的主要原因,你不能創建靜態方法的接口(還),所以你不能模擬出靜態方法來測試它。

二OO是程序功能等靜態方法作出了很大的意義在某些情況下,但他們總是可以做成一個對象的方法。

你要知道,你不能沒有一個黑客刪除此:

static void Main(string[] args) 
{ 
} 

啓動您的應用程序必須調用但沒有一個對象的引用代碼。所以他們給你靈活性,無論你選擇在你的場景中使用它們,都會根據你的要求來決定。

16

我會說靜態方法肯定是好的,當他們是函數,即他們沒有做任何IO,沒有任何內部狀態,只使用他們的參數來計算他們的返回值。

我還希望這個延伸到改變其參數的狀態,但如果這種過度進行,靜態方法應該是正確的,它主要經營的參數類的實例方法的方法。

2

靜態方法的另一個很好的方案是在一個特定的方式來構建的Factory pattern,你在哪裏,允許類的實例的實現。

考慮Calendar類,它具有一組靜態getInstance方法,每種情況下返回與所需TimeZone和/或Locale或默認灌注。

+0

我沒有使用依賴注入,也沒有(經常)模擬對象進行測試,但實現工廠的靜態方法會使嘲笑變得不可能,不是嗎? – 2009-10-07 09:34:53

3

靜態方法在大多數情況下都很好,在這種情況下,單例模式提供了太多的靈活性。

例如,以一個簡單的工具,如提高原始的力量 - 很明顯,你永遠需要有任何的多態性。原始值是靜態類型的,而數學運算是明確定義的,不會改變。這並不是說你永遠不會得到兩個differentimplementations無法在不重寫所有客戶端代碼的情況下切換它們的情況。


(諷刺關閉)

現代JVM是在如果只有一個實現接口的加載內嵌小型調用不錯。除非你對你的代碼進行了簡介,並且知道把你的工具分配給一個界面是一種開銷,否則你沒有理由不讓你的utility methods into an interface如果需要可以改變。

1

我經常使用靜態工廠方法來代替或與公共構造函數結合使用。

我這樣做,當我需要一個構造函數,做一些你不希望構造函數做的事情。即從文件或數據庫加載設置。

該方法還提供了基於他們所做的事情命名「構造函數」的可能性。當參數本身不足以找出構造函數中發生的情況時,這是特別有用的。

太陽將使用

Class.forName("java.lang.Integer"); 

Boolean.valueOf("true"); 
1

首先的這種方法,你不能排除靜態的方法是有原因的人還在使用它。

  1. 一些設計模式是基於靜態方法中,單例如:

    Config.GetInstance();

  2. 輔助函數,可以說你有一個字節流,你想要一個函數將它轉換成一串十六進制數字。

有靜態的方法很多用途,他說,這並不意味着,有些人濫用它太多(代碼審查是最好的選擇,當人們濫用代碼)。

1

Util類可以是靜態的。正如在上面的某個人中,使用轉義字符串。問題在於,這些utils類執行我們想要模擬的功能。例如,apache commons中的FileUtils類 - 通常情況下,我想要模擬文件交互而不必使用真實文件。如果這是一個實例類,那很容易。

1

重構靜態方法要容易得多。它不鼓勵不必要地提到使接頭緊密的現場成員。理解調用代碼也更容易,因爲它明確地傳遞了它所交互的任何對象。

0

通常我會在單個實例正常工作時避免使用靜態方法。該單個實例可以實現一個接口,並且可以輕鬆地進行模擬。我不是說從不,但我很少使用靜力學。我告訴我的團隊,如果他們想要使用靜態,應該由團隊清理。我的答案几乎從不是。

相關問題