2012-11-08 72 views
12

我有一個實用程序類,它有非靜態方法,沒有實例變量。所以我正在考慮將所有方法轉換爲static方法。我懷疑會有任何記憶或性能影響。但我只是想確認一下。工具類的靜態和非靜態方法的性能

將這種方法改爲static會對程序有任何性能影響嗎?

回答

17

最後要補充的是人們在這裏所說的話。

使用static方法的開銷稍小,因爲您已確保編譯時綁定。靜態方法調用將創建字節碼指令invokestatic。 ]

在典型的場景中,實例方法在運行時被綁定,並且將創建字節碼指令invokevirtual,其開銷高於invokestatic

但是,這隻會在數百萬次的迭代中變得相關,並且我會提醒你不要駕駛你的班級設計。從設計的角度去做什麼是有意義的。根據你的描述,static方法可能是最好的選擇。實際上,這是創建實用程序類的相對標準做法:

public class MyUtilities { 
    private MyUtilities() { } // don't let anyone construct it. 
    public static String foo(String s) { ... } 
} 
+1

這個故事有點複雜,因爲'invokevirtual'不是一個真正的機器指令。在最壞的情況下,它將作爲一個單形態的調用站點來實現,但是如果這個類是最終的(或者通過私有構造函數實際上是最終的),它將是一個硬連線的調用。即使沒有這些,運行時也可能會注意到,沒有任何子類,並且無論如何都可以接通電話。 –

+0

是的,我明白它並不能保證它沒有硬連線,但我試圖保持簡單的解釋,因爲大多數人不瞭解jvm的內部。 – Matt

+1

我必須說你的措辭有誤導性。這裏沒有「典型場景」:實例方法調用** always **編譯爲'invokevirtual';同樣使用靜態方法和'invokestatic'。 –

1

沒有狀態的實用程序類(例如java.lang.Math)具有公共靜態方法很常見。這樣你就不需要創建一個類的實例來使用它。

3

如果實用程序類未被子類化,那麼將不訪問實例變量的方法轉換爲static是個不錯的主意。你應該去通過代碼轉換和調用靜態的語法,即

int res = utilityInstance.someMethod(arg1, arg2); 

應轉換爲

int res = UtilityClass.someMethod(arg1, arg2); 

的清晰度。

不會有明顯的性能影響:雖然理論上靜態調用稍微便宜一點,但差別太小,在大多數情況下都不重要。

-1

所不同的是,你需要一個實例,以便使用它們,所以用戶必須做出一個實例,這將是一個

3

有兩個要求,即必須滿足的方法有資格轉換進入static

  1. 沒有實例變量被訪問(這在你的情況下會被滿足);
  2. 將永遠不會受到壓倒一切的影響(爲此,您可能需要考慮)。

然而,當這些要求得到滿足,它實際上是建議使方法靜態的,因爲它縮小了方法中運行的上下文。

最後,注意有沒有性能問題在這裏談談和任何理論上的區別,其實是贊成的靜態方法,因爲它們不涉及動態方法解析。但是,實例方法調用在任何相關的JVM實現中都非常快速。就內存而言,故事是一樣的:理論上的差異有利於靜態方法,但與單例實用程序類相比,沒有實際區別。

17

編輯:解決性能方面:更便宜的是不必創建一個毫無意義的東西的實例,但差異很可能是完全不相關。聚焦於清晰的設計隨着時間的推移變得更加重要。

實用的方法是經常靜態的,如果一個類中的所有方法都是靜態的,可能是值得做的類final和包括私有構造函數,防止 instantation。從根本上說,對於不代表任何真實「事物」的實用類,構建實例並不合乎邏輯,所以要防止它發生。另一方面,這確實降低了靈活性:如果這些實用方法中的任何一個包含您可能想要多變化變化的功能(例如,出於測試目的),則考慮將它們留作實例方法 - 並嘗試提取一些有意義的類名稱來代表涉及的「事物」。 (例如,FooConverter有意義的實例 - 一個FooUtil不。)當你要經常使用特定功能

+4

+1第二段。如果使用靜態方法,那麼將不可能交換實現。 –

+0

@MarkoTopolnik:在答案的開頭添加了一個部分。 –

0

靜態方法好主意。