我有一個實用程序類,它有非靜態方法,沒有實例變量。所以我正在考慮將所有方法轉換爲static
方法。我懷疑會有任何記憶或性能影響。但我只是想確認一下。工具類的靜態和非靜態方法的性能
將這種方法改爲static
會對程序有任何性能影響嗎?
我有一個實用程序類,它有非靜態方法,沒有實例變量。所以我正在考慮將所有方法轉換爲static
方法。我懷疑會有任何記憶或性能影響。但我只是想確認一下。工具類的靜態和非靜態方法的性能
將這種方法改爲static
會對程序有任何性能影響嗎?
最後要補充的是人們在這裏所說的話。
使用static
方法的開銷稍小,因爲您已確保編譯時綁定。靜態方法調用將創建字節碼指令invokestatic
。 ]
在典型的場景中,實例方法在運行時被綁定,並且將創建字節碼指令invokevirtual
,其開銷高於invokestatic
。
但是,這隻會在數百萬次的迭代中變得相關,並且我會提醒你不要駕駛你的班級設計。從設計的角度去做什麼是有意義的。根據你的描述,static
方法可能是最好的選擇。實際上,這是創建實用程序類的相對標準做法:
public class MyUtilities {
private MyUtilities() { } // don't let anyone construct it.
public static String foo(String s) { ... }
}
沒有狀態的實用程序類(例如java.lang.Math
)具有公共靜態方法很常見。這樣你就不需要創建一個類的實例來使用它。
如果實用程序類未被子類化,那麼將不訪問實例變量的方法轉換爲static
是個不錯的主意。你應該去通過代碼轉換和調用靜態的語法,即
int res = utilityInstance.someMethod(arg1, arg2);
應轉換爲
int res = UtilityClass.someMethod(arg1, arg2);
的清晰度。
不會有明顯的性能影響:雖然理論上靜態調用稍微便宜一點,但差別太小,在大多數情況下都不重要。
所不同的是,你需要一個實例,以便使用它們,所以用戶必須做出一個實例,這將是一個
有兩個要求,即必須滿足的方法有資格轉換進入static
:
然而,當這些要求得到滿足,它實際上是建議使方法靜態的,因爲它縮小了方法中運行的上下文。
最後,注意有沒有性能問題在這裏談談和任何理論上的區別,其實是贊成的靜態方法,因爲它們不涉及動態方法解析。但是,實例方法調用在任何相關的JVM實現中都非常快速。就內存而言,故事是一樣的:理論上的差異有利於靜態方法,但與單例實用程序類相比,沒有實際區別。
編輯:解決性能方面:更便宜的是不必創建一個毫無意義的東西的實例,但差異很可能是完全不相關。聚焦於清晰的設計隨着時間的推移變得更加重要。
實用的方法是經常靜態的,如果一個類中的所有方法都是靜態的,可能是值得做的類final
和包括私有構造函數,防止 instantation。從根本上說,對於不代表任何真實「事物」的實用類,構建實例並不合乎邏輯,所以要防止它發生。另一方面,這確實降低了靈活性:如果這些實用方法中的任何一個包含您可能想要多變化變化的功能(例如,出於測試目的),則考慮將它們留作實例方法 - 並嘗試提取一些有意義的類名稱來代表涉及的「事物」。 (例如,FooConverter
有意義的實例 - 一個FooUtil
不。)當你要經常使用特定功能
+1第二段。如果使用靜態方法,那麼將不可能交換實現。 –
@MarkoTopolnik:在答案的開頭添加了一個部分。 –
靜態方法好主意。
這個故事有點複雜,因爲'invokevirtual'不是一個真正的機器指令。在最壞的情況下,它將作爲一個單形態的調用站點來實現,但是如果這個類是最終的(或者通過私有構造函數實際上是最終的),它將是一個硬連線的調用。即使沒有這些,運行時也可能會注意到,沒有任何子類,並且無論如何都可以接通電話。 –
是的,我明白它並不能保證它沒有硬連線,但我試圖保持簡單的解釋,因爲大多數人不瞭解jvm的內部。 – Matt
我必須說你的措辭有誤導性。這裏沒有「典型場景」:實例方法調用** always **編譯爲'invokevirtual';同樣使用靜態方法和'invokestatic'。 –