web-dev-qa-db-ja.com

Java:静的メソッドを使うとき

静的メソッドをいつ使用するのか疑問に思いますか。いくつかのゲッターとセッターを持つクラス、1つか2つのメソッドがあり、それらのメソッドがそのクラスのインスタンスオブジェクトに対してのみ呼び出し可能であることを望みます。これは静的メソッドを使うべきだということですか?

例えば

Obj x = new Obj();
x.someMethod

または

Obj.someMethod

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

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

830
KP65

1つの経験則:「Objがまだ構築されていなくても、このメソッドを呼び出すことは意味がありますか?」と自問してください。もしそうなら、それは間違いなく静的でなければなりません。

そのため、Carクラスでは静的なメソッドdouble convertMpgToKpl(double mpg)を使用することができます。これは、誰もCarを作成したことがない場合でも、35mpgが何に変換されるのかを知りたい場合があるためです。しかしvoid setMileage(double mpg)(ある特定のCarの効率を設定する)は、Carが構築される前にこのメソッドを呼び出すことは考えられないため、静的にはできません。

(しかし、その逆は必ずしも真ではありません。時には2つのCarオブジェクトを含むメソッドを持っていて、それを静的にしたいと思うかもしれません。例えばCar theMoreEfficientOf( Car c1, Car c2 )。これは非静的バージョンに変換できますが、どちらのCarがより重要であるかの「特権的」な選択はないので、呼び出し元に、メソッドを呼び出すオブジェクトとして1台のCarを選択させるべきではありません。しかし、メソッド。

1341
not-just-yeti

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

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

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

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

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

  • メソッドを追加する:あなたは本当にStringクラスにremoveSpecialChars()インスタンスメソッドを持たせたかったのですが、そうではありません(そしてあなたのプロジェクトの特殊文字は他のものと違うかもしれないので(Javaはやや健全なので)追加することはできないので、ユーティリティクラスを作成し、removeSpecialChars(s)の代わりにs.removeSpecialChars()を呼び出します。甘い。

  • 純度:いくつかの注意を払うと、静的メソッドは 純粋な関数 になります。それが依存するのはそのパラメータです。データ入力、データ出力継承の問題を心配する必要がないため、これは読みやすくデバッグしやすいです。あなたはインスタンスメソッドでもそれを行うことができますが、コンパイラは(インスタンス属性への参照を許可しないこと、メソッドをオーバーライドすることなどによって)静的メソッドであなたをもう少し助けます。

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

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

160
tetsuo

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

私は自分のものが1つしかないことをどのように確認しますか

「どちらか一方だけを持つようにするにはどうすればよいですか」という問題は、うまく回避できます。メインのインスタンスは1つのApplicationFactoryのみをインスタンス化します。その結果、すべてのシングルトンのインスタンスは1つだけインスタンス化されます。

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

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

39
Alfred

staticメソッドは、呼び出されるためにオブジェクトを初期化する必要がないメソッドの一種です。 Javaのstatic関数でmainが使用されていることに気付きましたか?プログラムの実行は、オブジェクトが作成されずにそこから始まります。

次の例を見てください。

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

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

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

18
Kevin Sylvestre

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

11
duffymo

静的キーワードを任意の方法で適用する場合、それは静的方法と呼ばれます。

  1. 静的メソッドはクラスのオブジェクトではなくクラスに属します。
  2. クラスのインスタンスを作成せずに呼び出される静的メソッド。
  3. 静的メソッドは静的データメンバにアクセスでき、その値を変更できます。
  4. 静的メソッドは、クラスドットの静的名の名前を使用するだけでアクセスできます。 。 。例: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

11

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

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

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

8
Carsten

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

6
Sagar

静的メソッドはクラスで呼び出され、インスタンスメソッドはクラスのインスタンスで呼び出されるべきです。しかし、それは実際にはどういう意味ですか?これは便利な例です。

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

自動車クラスには、GetCarCount()というcountメソッドもあります。これは、作成(または建設)された自動車の総数を返します。自動車が建設されていない場合、このメソッドは0を返しますが、それでも呼び出すことができるはずなので、静的メソッドにする必要があります。

6

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

5
Jamey

静的メソッドはオブジェクトに対して呼び出す必要はありません。それはあなたがそれを使うときです。例:あなたのMain()は静的であり、あなたはそれを呼び出すためのオブジェクトを作成しません。

4
Vaishak Suresh

静的メソッドと変数は、Javaの 'Global'関数と変数の制御バージョンです。どのメソッドにclassname.methodName()またはclassInstanceName.methodName()としてアクセスできるか、つまり静的メソッドおよび変数には、クラス名とクラスのインスタンスを使用してアクセスできます。

クラスをstaticとして宣言することはできません(クラスがpublicとして宣言されている場合は、どこからでもアクセスできるため、意味がありません)。内部クラスはstaticとして宣言できます。

4
Manju Yadav

以下の場合は静的メソッドを使用できます。

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

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

    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)
    
  • 簡単な機能として使いたい。入力は明示的に渡され、結果データを戻り値として取得します。継承、オブジェクトのインスタンス化は考えられません。 簡潔で読みやすい

NOTE:静的メソッドのテスト容易性を主張する人はほとんどいませんが、静的メソッドもテストできます。 jMockitを使えば、静的メソッドをモックすることができます。 テスト容易性。以下の例:

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

静的:Obj.someMethod

メソッドへのクラスレベルのアクセスを提供したい場合、つまりメソッドがクラスのインスタンスなしで呼び出し可能でなければならない場合、staticを使用します。

3
Finbarr

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

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

3
rashedcs

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

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

静的メソッドをいつ使用するのか疑問に思いますか。

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

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

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

クラスのインスタンスオブジェクトのmethodにアクセスする必要がある場合、そのメソッドはstaticではないはずです。

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

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

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

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

Eclipse setting

1
ave4496

静的メソッドが適切な場合

静的メソッドまたは静的変数が使用されているのは2つの状況のみであり、それは憎悪ではありません。

  1. グローバル変数ではなく、真のグローバル定数を宣言します。グローバル定数。例:Math.PI。これは、ユニバースのインスタンスが1つあり、ユニバースシングルトンには、変化しないプロパティPIが存在する数学的概念シングルトンが含まれていることを実際に言うための公正な略記です。私たちはオブジェクト指向の責任の文脈でPIについて考えないことに慣れているため、この概念は私たちにとって奇妙に思えます。異なる数学的概念と定数を持つ別の宇宙が存在する奇妙なゲームを設計していると、より明白になります。
  2. オブジェクトの作成。静的メソッドは、オブジェクト作成の貴重で有効な方法です。異なる引数を取るオーバーロードされたコンストラクターはあまり明確ではなく、静的コンストラクターに置き換えることでより明確になることがよくあります。

静的メソッドが悪いとき?

  1. 静的メソッドについて考える1つの方法は、グローバルプロシージャとしてです。基本的に、静的メソッドはどこからでもどこでも呼び出すことができます。実際にクラスが「タグ」としてのみ使用される場合、クラスの一部のふりをして、メソッドを論理的な分割によって整理します。グローバルプロシージャの作成は、オブジェクト指向設計の正反対だからです。

  2. 静的メソッドのもう1つの大きな問題は、テスト容易性です。ソフトウェアを構築する場合、テスト容易性は大きな問題です。静的メソッドは、特に具象クラスの新しいインスタンスを作成する場合、テストが難しいことで有名です。従来のコードで作業したことがあり、静的メソッドの単体テストを作成しようとしたことがあるなら、あなたは私の痛みを知っています。

  3. 静的メソッドもポリモーフィックではありません。クラスで静的メソッドを作成する場合、その動作をオーバーライドすることはありません。その実装へのハードコード化された参照で立ち往生しています。

最終単語

したがって、静的メソッドを作成するときは、慎重に検討することを忘れないでください。私はそれらを決して使用しないことを主張していません。私は本当に正当な理由があると主張し、最初に静的メソッドが本当に状態情報を使用できる別のクラスに属しているかどうかを確認するためにチェックしています。

0
Tell Me How