method教學 Java:何時使用靜態方法




static method python (17)

在閱讀Misko的文章後,我認為從測試的角度來看, 靜態方法是不好的。 你應該有factories而不是(可能使用像Guice這樣的依賴注入工具)。

我如何確保我只有一件事

只有一件事“我如何確保我只有一件東西”的問題很好地被迴避了。 你只在你的main中實例化一個ApplicationFactory,結果你只實例化所有單例的一個實例。

靜態方法的基本問題是它們是程序代碼

靜態方法的基本問題是它們是程序代碼。 我不知道如何對程序代碼進行單元測試。 單元測試假定我可以孤立地實例化我的一個應用程序。 在實例化過程中,我使用mocks / friendlies替換真正的依賴關係。 通過程序編程,沒有任何東西可以“連線”,因為沒有對象,代碼和數據是分開的。

我想知道什麼時候使用靜態方法? 假如我有一個有幾個getter和setter的類,一個或兩個方法,我希望這些方法只能在類的實例對像上調用。 這是否意味著我應該使用靜態方法?

例如

Obj x = new Obj();
x.someMethod

要么

Obj.someMethod

(這是靜態的方式?)

我很困惑!


不,靜態方法不與一個實例關聯; 他們屬於這個班級。 靜態方法是你的第二個例子; 實例方法是第一個。


靜態方法是Java中的方法,可以在不創建類的對象的情況下調用。 它屬於班級。

當我們不需要使用實例調用方法時,我們使用靜態方法。


靜態方法和變量是Java中'Global'函數和變量的受控版本。 在哪些方法可以作為classname.methodName()classInstanceName.methodName()來訪問,即靜態方法和變量可以使用類名稱以及類的實例來訪問。

類不能被聲明為靜態的(因為它是沒有意義的,如果一個類聲明為public,它可以從任何地方訪問),內部類可以聲明為靜態的。


靜態方法有兩個主要目的:

  1. 對於不需要任何對象狀態的實用程序或幫助程序方法。 由於不需要訪問實例變量,因此使用靜態方法就不需要調用者實例化對象,只需調用該方法即可。
  2. 對於類的所有實例共享的狀態,如計數器。 所有實例必須共享相同的狀態。 僅僅使用該狀態的方法也應該是靜態的。

當您希望能夠在沒有該類的實例的情況下訪問該方法時,請使用靜態方法。


我想知道什麼時候使用靜態方法?

  1. static方法的一個常見用途是訪問static字段。
  2. 但是你可以有static方法,而不需要引用static變量。 沒有引用static變量的Helper方法可以在java.lang.Math等java類中找到

    public static int min(int a, int b) {
        return (a <= b) ? a : b;
    }
    
  3. 另一個用例是,我可以將這些方法與synchronized方法結合起來,就是在多線程環境中實現類級鎖定。

假如我有一個有幾個getter和setter的類,一個或兩個方法,我希望這些方法只能在類的實例對像上調用。 這是否意味著我應該使用靜態方法?

如果你需要訪問類的實例對象的方法,你的方法應該是非靜態的。

Oracle文檔page提供了更多細節。

並非所有實例和類變量和方法的組合都是允許的:

  1. 實例方法可以直接訪問實例變量和實例方法。
  2. 實例方法可以直接訪問類變量和類方法。
  3. 類方法可以直接訪問類變量和類方法。
  4. 類方法不能直接訪問實例變量或實例方法 - 它們必須使用對象引用。 另外,類方法不能使用this關鍵字,因為沒有實例可以引用它。

在eclipse中,你可以啟用一個警告來幫助你檢測潛在的靜態方法。 (突出顯示的行上方是另一個我忘記強調的行)


實際上,我們在一個類中使用靜態屬性和方法,當我們想要使用我們的程序的某些部分時,應該存在,直到我們的程序運行。 我們知道,為了操作靜態屬性,我們需要靜態方法,因為它們不是實例變量的一部分。 而沒有靜態方法,操縱靜態屬性是非常耗時的。


如果您使用任何方法應用static關鍵字,則稱為靜態方法。

  1. 靜態方法屬於類而不是類的對象。
  2. 無需創建類的實例即可調用的靜態方法。
  3. 靜態方法可以訪問靜態數據成員並可以更改它的值。

//改變所有對象(靜態字段)的公共屬性的程序。

class Student9{  
 int rollno;  
 String name;  
 static String college = "ITS";  

 static void change(){  
 college = "BBDIT";  
 }  

 Student9(int r, String n){  
 rollno = r;  
 name = n;  
 }  

 void display (){System.out.println(rollno+" "+name+" "+college);}  

public static void main(String args[]){  
Student9.change();  

Student9 s1 = new Student9 (111,"Indian");  
Student9 s2 = new Student9 (222,"American");  
Student9 s3 = new Student9 (333,"China");  

s1.display();  
s2.display();  
s3.display();  
}  }

O / P:111印度BBDIT 222美國BBDIT 333中國BBDIT


靜態: Obj.someMethod

當您想要為方法提供類級別訪問權時使用static ,例如,應該在沒有類實例的情況下調用方法。


有一些有效的理由使用靜態方法:

  • 性能 :如果你想要運行一些代碼,並且不想實例化一個額外的對象來實現,可以將它轉換為靜態方法。 JVM也可以優化靜態方法(我想我曾經讀過James Gosling聲明你不需要JVM中的自定義指令,因為靜態方法一樣快,但找不到源代碼 - 因此它可能是完全錯誤的)。 是的,這是微型優化,可能不需要。 我們的程序員從來不會做不必要的事情,只是因為它們很酷,對吧?

  • 實用性 :不是調用new Util().method(arg)Util.method(arg)調用Util.method(arg)method(arg)靜態導入。 更簡單,更短。

  • 添加方法 :你真的希望類String有一個removeSpecialChars()實例方法,但它不存在(它不應該,因為你的項目的特殊字符可能不同於其他項目),並且你不能添加它(因為Java有點理智),所以你創建了一個實用類,並調用removeSpecialChars(s)而不是s.removeSpecialChars() 。 甜。

  • 純度 :採取一些預防措施,你的靜態方法將是一個純函數 ,也就是說,它唯一依賴的是它的參數。 數據輸入,數據輸出。 這樣更容易閱讀和調試,因為您不需要擔心繼承問題。 你也可以用實例方法來實現,但編譯器會通過靜態方法(不允許引用實例屬性,覆蓋方法等)幫助你多一點。

如果你想創建一個單例,你還必須創建一個靜態方法,但是......不。 我的意思是,三思。

現在,更重要的是, 為什麼你不想創建一個靜態方法? 基本上, 多態性不在窗口中 。 你將無法重寫該方法, 也不能在接口中聲明它(在 Java 8之前) 。 它從設計中需要很大的靈活性。 另外,如果你需要狀態 ,如果你不小心,最終會出現大量的並發錯誤和/或瓶頸。


靜態方法可以使用

  • 一個人不想對一個實例執行一個動作(實用程序方法)

    正如在這篇文章中提到的上述答案中的幾條所述,將英里轉換為公里,或者從華氏溫度計算為攝氏溫度,反之亦然。 通過使用靜態方法的這些示例,它不需要在堆內存中實例化整個新對象。 考慮下面

    1. new ABCClass(double farenheit).convertFarenheitToCelcium() 
    2. ABCClass.convertFarenheitToCelcium(double farenheit)
    

    前者為每個方法調用, 性能,實用創建一個新的類占用空間。 例如下面的Math和Apache-Commons庫StringUtils類:

    Math.random()
    Math.sqrt(double)
    Math.min(int, int)
    StringUtils.isEmpty(String)
    StringUtils.isBlank(String)
    
  • 一個人想作為一個簡單的功能使用。 輸入被顯式傳遞,並將結果數據作為返回值。 繼承,對象實例不會出現在圖片中。 簡潔,易讀

注意 :很少有人會反對靜態方法的可測試性,但靜態方法也可以被測試! 使用jMockit,可以模擬靜態方法。 可測試性 。 示例如下:

new MockUp<ClassName>() {
    @Mock
    public int doSomething(Input input1, Input input2){
        return returnValue;
    }
};

一個經驗法則是:問問自己“調用這個方法是否合理,即使沒有構造Obj?” 如果是這樣,它肯定應該是靜態的。

所以在Car類中,你可能會有一個double convertMpgToKpl(double mpg) ,它可能是靜態的,因為人們可能想知道35mpg轉換成什麼,即使沒有人構建過Car。 但是void setMileage(double mpg) (設置一個特定Car的效率)不能是靜態的,因為在任何Car構造之前調用該方法是不可想像的。

(順便說一句,反過來並不總是正確的:你有時可能有一個涉及兩個Car對象的方法,並且仍然希望它是靜態的,例如Car theMoreEfficientOf( Car c1, Car c2 ) 。雖然這可以轉換為非靜態版本,有人會認為,既然沒有“特權”選擇哪個車更重要,你不應該強迫呼叫者選擇一個車作為你調用該方法的對象。儘管如此,對於所有靜態方法的一小部分)。


靜態方法在類的所有實例之間共享,開發人員通常使用靜態關鍵字與實用程序方法,這些方法執行應用程序中任何位置常用的常用功能。

如果以下條件適用,則使您的方法靜態:

  1. 您的方法具有常用於整個應用程序的常用功能。
  2. 你的方法不使用實例變量。
  3. 你的方法接受輸入作為參數,做一些常用的功能,然後返回一些結果。

PS:值得一提的是,嘲諷靜態方法非常困難甚至(不可能),嘲笑是單元測試中用來偽造某些方法的業務的一種機制。

有關更多詳細信息,請在java中檢查: Static關鍵字


靜態方法與實例無關,所以它們不能訪問類中的任何非靜態字段。

如果方法不使用類的任何字段(或僅使用靜態字段),則可以使用靜態方法。

如果使用某個類的任何非靜態字段,則必須使用非靜態方法。


static方法是一種不需要為了被調用而初始化任何對象的方法。 你有沒有註意到在Java的main功能中使用static ? 程序從那裡開始執行,不需要創建對象。

考慮下面的例子:

 class Languages 
 {
     public static void main(String[] args) 
     {
         display();
     }

     static void display() 
     {
         System.out.println("Java is my favorite programming language.");
     }
  }






static-methods