Java:静的メソッドを使用する場合


911

静的メソッドをいつ使用するのですか?いくつかのゲッターとセッター、またはメソッドを1つまたは2つ持つクラスがあり、それらのメソッドをクラスのインスタンスオブジェクトでのみ呼び出し可能にしたいとします。これは、静的メソッドを使用する必要があることを意味しますか?

例えば

Obj x = new Obj();
x.someMethod

または

Obj.someMethod

(これは静的な方法ですか?)

私はかなり混乱しています!

回答:


1458

経験則:「オブジェクトがまだ作成されていなくても、このメソッドを呼び出すことは理にかなっていますか?」もしそうなら、それは間違いなく静的でなければなりません。

したがって、クラスにCarはメソッドがある場合があります。

double convertMpgToKpl(double mpg)

...これは静的です。なぜなら、誰もを作成したことがなくても、35mpgが何に変換されるのかを知りたい場合があるからCarです。しかし、この方法(ある特定のの効率を設定するCar):

void setMileage(double mpg)

... Car構成する前にメソッドを呼び出すことは考えられないため、静的にすることはできません。

(ちなみに、その逆は常に正しいとは限りません。2つのCarオブジェクトを含むメソッドがあり、それを静的にしたい場合があります。例:

Car theMoreEfficientOf( Car c1, Car c2 )

これは非静的バージョンに変換される可能性がありますが、「特権付き」の選択肢Carはより重要ではないため、呼び出し元にCar、呼び出すオブジェクトとして強制的に選択させるべきではないと主張する人もいます。メソッドオン。ただし、この状況は、すべての静的メソッドのごく一部を占めています。)


325
ここにいくつかの良い例があります。ただし、インスタンス間で何かが変更されないことがわかっている場合、「静的」はしばしば価値があると付け加えます。これが事実である場合、私は本当に「単一の責任の原則」を検討します。これは、クラスには1つの責任があり、したがって変更する理由は1つだけであることを意味します。「ConvertMpgToKpl(double mpg)」関数や類似のメソッドを独自のクラスに移動することを検討する必要があると思います。車オブジェクトの目的は、車のインスタンス化を可能にすることであり、車間の比較を提供することではありません。これらはクラスの外部にある必要があります。
ザックヤンセン、2012

34
どちらかというとメソッドだと思いますCar#isMoreEfficientThan(Car)。ネクタイでどちらの車を返すかは任意ではないという利点があります。メソッドのタイトルから、ネクタイで何が返されるかは明らかです。
たけた

5
また、外部リソース(ファイルシステム、データベースなど)を使用する静的メソッドを作成する場合にも注意が必要です。このタイプの静的は、消費するメソッドをテストすることを非常に困難にする可能性があります。私は個人的に、静粛性を「実用性」の領域に保つよう努めています。
Seth M. 14

7
実際には、コンパレータとして実装する必要があります。
Dogweather、2015

3
@ B1KMusicもちろんです。「どちらの車が引き分けで返される」とは、「呼び出された車への真のマップと、渡された車への偽のマップ」です。あいまいさはありません。
Cruncher

538

次のシナリオでのみ静的メソッドを定義します。

  1. ユーティリティクラスを作成していて、それらが変更されていない場合。
  2. メソッドがインスタンス変数を使用していない場合。
  3. インスタンスの作成に依存しない操作がある場合。
  4. すべてのインスタンスメソッドで簡単に共有できるコードがある場合は、そのコードを静的メソッドに抽出します。
  5. メソッドの定義が変更またはオーバーライドされないことが確実な場合。静的メソッドとしてオーバーライドすることはできません。

45
良い点、しかし、あなたがいる場合、彼らは要件ですしたいメソッド静的を作るために、ないものを作るための理由。
tetsuo

4
要件5に関する@Mohd:メソッドが変更またはオーバーライドされないことが100%確実になるのはいつですか?静的メソッドを作成するときに考慮できない未知の要因が常にあるわけではありませんか?
PixelPlex 2015

8
「Utility-Classes」は推論するのが非常に困難です。悪い点は、遅かれ早かれ、すべてがユーティリティのように見えることです(ええ、私は肥大化し、触れられず、十分にテストされていない「util」パッケージを参照しています)。また、テストケースでさらに作業が必要になります(静的ユーティリティをモックするのは難しい)。最初にオブジェクトを優先します。
セルジオ

2
@Mohdこの答えはまさに私が探しているものです。マルチスレッドで静的メソッドを使用すると、多くの問題に直面しました。ポイント2、3について詳しく説明していただけますか(例:100のいいね)
Prakash Pandey

静的変数やメソッドを使用する場合は、「静的クラス」を発明する必要があると思います。
ロバートロチャ

182

静的メソッドを使用する正当な理由がいくつかあります。

  • パフォーマンス:いくつかのコードを実行したいが、そうするために追加のオブジェクトをインスタンス化したくない場合は、それを静的メソッドに入れます。JVMは静的メソッドも大幅に最適化できます(James Goslingを読んだことがあるので、JVMでカスタム命令は必要ないことを宣言しました。静的メソッドも同じくらい高速ですが、ソースを見つけることができなかったためです。完全に偽である可能性があります)。はい、それはマイクロ最適化であり、おそらく不要です。そして私たちプログラマーは、クールだからといって不要なことをすることはありませんよね?

  • 実用性:を呼び出す代わりにnew Util().method(arg)、を呼び出すUtil.method(arg)method(arg)、静的インポートを使用します。より簡単、より短く。

  • メソッドの追加:クラスStringにremoveSpecialChars()インスタンスメソッドが本当に必要でしたが、それはありません(プロジェクトの特殊文字は他のプロジェクトの特殊文字と異なる可能性があるため、必要ありません)。また、それを追加することはできません(Javaは多少まともです)。そのため、ユーティリティクラスを作成し、removeSpecialChars(s)ではなくを呼び出しますs.removeSpecialChars()。甘い。

  • 純度:いくつかの予防策を講じると、静的メソッドは純粋な関数になります。つまり、それが依存するのはパラメーターだけです。データイン、データアウト。継承の癖を気にする必要がないため、これは読みやすく、デバッグも簡単です。インスタンスメソッドでもこれを行うことができますが、コンパイラは静的メソッドでもう少し役立ちます(インスタンス属性への参照を許可しない、メソッドをオーバーライドするなど)。

シングルトンを作成する場合は、静的メソッドも作成する必要がありますが、...しないでください。つまり、よく考えます。

さて、もっと重要なことですがなぜ静的メソッドを作成したくないのでしょうか?基本的に、ポリモーフィズムはウィンドウの外に出ます。メソッドをオーバーライドしたり、インターフェースで宣言したりすることは できません(Java 8以前)。それはあなたのデザインから多くの柔軟性を取り除きます。また、状態が必要な場合、注意しないと、多くの同時実行バグやボトルネックが発生します。


1
staticが役立つ場合について、ここに記載されている多くの正当な理由があります。一つは、より多くの私が考えることができ、そのような方法のためのユニットテストを書くことはただのシンプルであるということです
nilesh

@tetsuoありがとう!あなたの説明は非常に明確であり、提供される理由は非常に論理的であり、非常に理にかなっています。
Deniss M.

3
そして私たちプログラマーは、クールだからといって不要なことをすることはありませんよね?+1
スカラムーシュ2018年

これは、静的メソッドは、完全な名前の関数となったstackoverflow.com/questions/155609/...
Ivanzinho

私はパフォーマンスと実用性に同意しますが、純度には同意しません。静的メソッドは、クラスの静的メンバー(プライベートの場合があります)を変更できます。これは便利です。たとえば、「静的同期int allocateID(){return idNext ++;}」のようなメソッドを使用できます。実際、静的メソッドは、副作用に関して非静的メソッドと同じくらい純粋または不純な場合があります。
Adam Gawne-Cain

42

Miskoの記事を読んだ後、静的なメソッドはテストの観点から見て悪いと思います。代わりにファクトリーが必要です(多分Guiceのような依存性注入ツールを使用します)。

私が何かを持っていることを確実にする方法

何かを1つだけ持つ「何かを1つだけ持っていることをどのように確認するか」という問題はうまく回避されます。メインで単一のApplicationFactoryのみをインスタンス化すると、すべてのシングルトンの単一のインスタンスのみがインスタンス化されます。

静的メソッドの基本的な問題は、それらが手続き型コードであることです

静的メソッドの基本的な問題は、それらが手続き型コードであることです。手続き型コードを単体テストする方法がわかりません。単体テストでは、アプリケーションの一部を分離してインスタンス化できると想定しています。インスタンス化中に、依存関係を実際の依存関係を置き換えるモック/フレンドリーに関連付けます。手続き型プログラミングでは、オブジェクトがなく、コードとデータが分離されているため、「配線」するものはありません。


20
手続き型コードを単体テストできないという部分がわかりません。静的メソッドとクラスを「ユニット」として使用して、正しい入力を正しい出力にマッピングするテストケースをセットアップするだけではありませんか?
tjb 2012年

2
これらの機能をテストするためにそれを行うことができます。しかし、テストしたい他のクラスでこれらの静的メソッドを使用する場合、クラスをインスタンス化できないため、それら(モック/フレンドリー)などを偽造することはできないと思います。
アルフレッド

4
@Alfred:静的メソッドをモックする機能を持つPowerMockをご覧ください。PowerMockを使用すると、モックできないメソッドの依存関係が見つかるシナリオがあります。
カルレス・サラ

7
PowerMockを使用して静力学を単体テストできますが、すぐにPermgenスペースが不足していることに気付き(Tシャツを入手しました)、それでもまだ厄介です。(真のOO言語での10年以上の自分自身の経験に基づいており、Cからの移行ではない)を知っている場合を除いて、それを行わないでください。真剣に、私が今まで見た中で最悪のコードは、組み込み開発者による静的の使用から来たものであり、ほとんどの場合、それは永遠にそれで行き詰まり、さらにコードを追加すると、変更できないモノリスにさらにしっかりと固定されました。疎結合:いいえ、テスト可能:やっと、変更可能:絶対に。避ける!
user1016765 2014年

14
静的状態に依存する静的メソッドのテストの難しさを理解できます。しかし、またはのようなステートレスな静的メソッドをテストしているとき、すべての依存関係を渡すことができるメソッドでさえ、ユニットテストがどのように妨げられるかはわかりません。簡単な経験則として、手続き型ロジックをモックアウトする理由がある場合は、静的メソッドに含めないでください。私はモックにする理由があったことがありませんか。Math.abs()Arrays.sort()Arrays.sort()Math.abs()
アンディ

36

staticこの方法は、それが呼ばれるようにするために初期化される任意のオブジェクトを必要としない方法の一種です。Java staticmain関数で使用されていることに気づきましたか?プログラムの実行は、オブジェクトが作成されずにそこから開始されます。

次の例を考えてみます。

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

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

ベストアンサー
Yahya

20

Javaの静的メソッドは(そのインスタンスではなく)クラスに属します。これらはインスタンス変数を使用せず、通常はパラメーターから入力を受け取り、それに対してアクションを実行してから、結果を返します。インスタンスメソッドはオブジェクトに関連付けられており、その名前が示すように、インスタンス変数を使用できます。


12

いいえ、静的メソッドはインスタンスに関連付けられていません。彼らはクラスに属しています。静的メソッドは2番目の例です。インスタンスメソッドが最初です。


1
オブジェクトの状態を操作する必要がない場合は、静的メソッドを使用する必要があります。
MastAvalons

11

いずれかの方法で静的キーワードを適用する場合、それは静的メソッドと呼ばれます。

  1. 静的メソッドは、クラスのオブジェクトではなくクラスに属しています。
  2. クラスのインスタンスを作成する必要なしに呼び出される静的メソッド。
  3. staticメソッドは静的データメンバーにアクセスし、その値を変更できます。
  4. 静的メソッドには、クラスの名前static static nameを使用するだけでアクセスできます。。。例:Student9.change();
  5. クラスの非静的フィールドを使用する場合は、非静的メソッドを使用する必要があります。

//すべてのオブジェクトの共通プロパティを変更するプログラム(静的フィールド)。

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


10

静的メソッドはインスタンスに関連付けられていないため、クラスの非静的フィールドにアクセスできません。

メソッドがクラスのフィールドをまったく使用しない(または静的フィールドのみを使用する)場合は、静的メソッドを使用します。

クラスの非静的フィールドを使用する場合は、非静的メソッドを使用する必要があります。


1
明確で短く、簡単な答え。
Josi

8

静的メソッドはクラスで呼び出し、インスタンスメソッドはクラスのインスタンスで呼び出す必要があります。しかし、それは実際にはどういう意味ですか?ここに便利な例があります:

車のクラスにはAccelerate()というインスタンスメソッドがある場合があります。車が実際に存在する(構築されている)場合にのみ、車を加速することができます。したがって、これはインスタンスメソッドになります。

車のクラスには、GetCarCount()というカウントメソッドも含まれる場合があります。これにより、作成(または作成)された車の総数が返されます。車が構築されていない場合、このメソッドは0を返しますが、それでも呼び出すことができるはずなので、静的メソッドでなければなりません。


6

実際、クラスで静的プロパティとメソッドを使用します。プログラムを実行するまで、プログラムの一部を使用したい場合はそこに存在する必要があります。また、静的プロパティを操作するには、インスタンス変数の一部ではないため、静的メソッドが必要であることがわかります。また、静的メソッドがないと、静的プロパティを操作するのに時間がかかります。


静的変数に状態を保持することは、マルチスレッドの安全性、デバッグ、データのカプセル化などの多くの理由で行うのが悪いことです。静的メソッドは、それらが純粋な関数である場合は問題ありません(変更せずに、パラメーターのみで機能します)。良い例は、たとえば数学計算などのユーティリティクラスです。
Vladimir Demirev

5

クラスのインスタンスなしでメソッドにアクセスできるようにする場合は、静的メソッドを使用します。


29
これは、プログラムの設計に根拠を与えるものではありません。
adamjmarkham 2012年

4

静的: Obj.someMethod

staticメソッドへのクラスレベルのアクセスを提供する場合、つまり、クラスのインスタンスがなくてもメソッドを呼び出すことができる場合に使用します。


4

静的メソッドは、オブジェクトで呼び出す必要はありません。それは、それを使用するときです。例:Main()は静的であり、それを呼び出すオブジェクトを作成しません。


1
わーい!Java noobieの質問をグーグル検索しながら、私がどこに来たか見てください!それは小さな世界です:-)
Deepak

1
@Deepak小さな世界は確かに:)
Vaishak Suresh

4

静的メソッドと変数は、Javaの「グローバル」関数と変数の制御されたバージョンです。classname.methodName()またはとしてアクセスできるメソッドclassInstanceName.methodName()。つまり、静的メソッドと変数には、クラス名とクラスのインスタンスを使用してアクセスできます。

クラスは静的として宣言できません(意味がないためです。クラスがパブリックとして宣言されている場合、どこからでもアクセスできます)、内部クラスは静的として宣言できます。


3

静的メソッドは次の場合に使用できます

  • インスタンス(ユーティリティメソッド)でアクションを実行したくない

    この投稿の上記の回答のいくつかで述べたように、マイルをキロメートルに変換するか、気温を華氏から摂氏に、またはその逆に計算します。静的メソッドを使用するこれらの例では、新しいオブジェクト全体をヒープメモリにインスタンス化する必要はありません。以下を検討

    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;
    }
};

3

静的メソッドは、クラスのオブジェクトを作成せずに呼び出すことができるJavaのメソッドです。クラスに属しています。

インスタンスを使用してメソッドを呼び出す必要がない場合は、静的メソッドを使用します。


2

静的メソッドをいつ使用するのですか?

  1. staticメソッドの一般的な用途は、staticフィールドへのアクセスです。
  2. しかしstaticstatic変数を参照せずにメソッドを持つことができます。static変数を参照しないヘルパーメソッドは、java.lang.Mathなどの一部のJavaクラスにあります。

    public static int min(int a, int b) {
        return (a <= b) ? a : b;
    }
  3. もう1つの使用例として、これらのメソッドをメソッドと組み合わせるとsynchronized、マルチスレッド環境でのクラスレベルのロックの実装が考えられます。

いくつかのゲッターとセッター、またはメソッドを1つまたは2つ持つクラスがあり、それらのメソッドをクラスのインスタンスオブジェクトでのみ呼び出し可能にしたいとします。これは、静的メソッドを使用する必要があることを意味しますか?

クラスのインスタンスオブジェクトのメソッドにアクセスする必要がある場合、メソッドは非静的である必要があります。

詳細については、Oracleのドキュメントページを参照してください。

インスタンス変数とクラス変数およびメソッドのすべての組み合わせが許可されるわけではありません。

  1. インスタンスメソッドは、インスタンス変数とインスタンスメソッドに直接アクセスできます。
  2. インスタンスメソッドは、クラス変数とクラスメソッドに直接アクセスできます。
  3. クラスメソッドは、クラス変数とクラスメソッドに直接アクセスできます。
  4. クラスメソッドは、インスタンス変数またはインスタンスメソッドに直接アクセスできません。オブジェクト参照を使用する必要があります。また、thisが参照するインスタンスがないため、クラスメソッドはthisキーワードを使用できません。

通常の方法で静的フィールドにアクセスできませんか?次に、これA common use for static methods is to access static fields.は議論ではありません。
パーサー

2

静的メソッドには2つの主な目的があります。

  1. オブジェクトの状態を必要としないユーティリティまたはヘルパーメソッドの場合。インスタンス変数にアクセスする必要がないため、静的メソッドを使用すると、呼び出し元がメソッドを呼び出すためだけにオブジェクトをインスタンス化する必要がなくなります。
  2. カウンターなど、クラスのすべてのインスタンスで共有される状態の場合。すべてのインスタンスが同じ状態を共有する必要があります。その状態を単に使用するメソッドも静的でなければなりません。

1

日食では、潜在的な静的メソッドを検出するのに役立つ警告を有効にすることができます。(強調表示された行の上には、強調表示するのを忘れた別の行があります)

日食設定


0

コードでメソッドを呼び出すオブジェクトを作成したくない場合は、そのメソッドを静的として宣言するだけです。静的メソッドはインスタンスを呼び出す必要がないため、ここでのキャッチはすべての静的メソッドがJVMによって自動的に呼び出されるわけではないためです。この特権は、Javaのmain() "public static void main [String ... args]"メソッドによってのみ享受されます。これは、実行時にこれが、JVMがエントリポイントとして求めるメソッドSignature public "static" void main []であるためです。コードの実行を開始します。

例:

public class Demo
{
   public static void main(String... args) 
   {
      Demo d = new Demo();

      System.out.println("This static method is executed by JVM");

     //Now to call the static method Displ() you can use the below methods:
           Displ(); //By method name itself    
      Demo.Displ(); //By using class name//Recommended
         d.Displ(); //By using instance //Not recommended
   }

   public static void Displ()
   {
      System.out.println("This static method needs to be called explicitly");
   }
} 

出力:-この静的メソッドはJVMによって実行されますこの静的メソッドは明示的に呼び出す必要がありますこの静的メソッドは明示的に呼び出す必要がありますこの静的メソッドは明示的に呼び出す必要があります

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.