インスタンス化されるように設計されたクラスがあるとしましょう。私はクラス内にいくつかのプライベートな「ヘルパー」メソッドを持っています。これらのメソッドはクラスメンバへのアクセスを必要とせず、引数のみで動作し、結果を返します。
public class Example {
private Something member;
public double compute() {
double total = 0;
total += computeOne(member);
total += computeMore(member);
return total;
}
private double computeOne(Something arg) { ... }
private double computeMore(Something arg) {... }
}
computeOne
およびcomputeMore
を静的メソッドとして指定する特別な理由はありますか、または指定しない特別な理由はありますか?
問題を引き起こさずに静的であっても、それらを非静的のままにしておくのは確かに最も簡単です。
このようなヘルパーメソッドはprivate static
であることが望ましいです。オブジェクトの状態を変更しないことが読者に明確になります。私のIDEは、イタリック体で静的メソッドの呼び出しも表示するので、署名を見ずにメソッドが静的であることがわかります。
私の個人的な好みは、それらが静的であると宣言することです。これは、それらがステートレスであることの明確なフラグだからです。
答えは...それは依存します。
メンバーが処理しているオブジェクトに固有のインスタンス変数である場合、なぜそれをパラメーターとして渡すのですか?
例えば:
public class Example {
private Something member;
public double compute() {
double total = 0;
total += computeOne();
total += computeMore();
return total;
}
private double computeOne() { /* Process member here */ }
private double computeMore() { /* Process member here */ }
}
静的ヘルパーメソッドを宣言する理由の1つは、this
またはsuper
の前にクラスコンストラクターで呼び出す必要がある場合です。例えば:
public class MyClass extends SomeOtherClass {
public MyClass(String arg) {
super(recoverInt(arg));
}
private static int recoverInt(String arg) {
return Integer.parseInt(arg.substring(arg.length() - 1));
}
}
これは少し不自然な例ですが、この場合recoverInt
をインスタンスメソッドにすることはできません。
私は、プライベート静的メソッドの明確な利点を本当に考えることはできません。そうは言っても、それらを非静的にすることには特別な利点はありません。主に表示の問題です。オブジェクトを変更していないという事実を明確に強調するために、静的にしたい場合があります。
異なるアクセス特権を持つメソッドの場合、主に2つの引数があると思います。
それに加えて、違いは非常に小さく、このポインターがインスタンスメソッドに渡した余分なものが大きな違いを生むことを強く疑います。
正解は次のとおりです。
フィールドから情報を取得せず、フィールドに情報を入力しないメソッドは、インスタンスメソッドである必要はありません。クラスまたはオブジェクトのフィールドを使用または変更しないメソッドは、静的メソッドでもあります。
または[静的として宣言しない]特定の理由?
はい。
それらをインスタンスメソッドとして保持することにより、後で別の実装を提供できるようになります。
ばかげているように聞こえるかもしれませんが(実際、これらのメソッドが50行のプログラムでのみ使用される場合)、より大きなアプリケーションや他の誰かが使用するライブラリーでは、より良い実装を選択することができますが、既存のコードを壊したい。
したがって、サブクラスを作成し、新しいバージョンでそれを返します。メソッドはインスタンスメソッドとして宣言されているため、ポリモーフィズムに仕事をさせるだけです。
さらに、コンストラクターをプライベートにして、同じ理由で静的ファクトリーメソッドを提供することもできます。
したがって、私の推奨事項は、それらをインスタンスメソッドとして保持し、可能であれば静的なものを避けることです。
言語が提供するダイナミズムを活用してください。
多少関連するビデオについてはこちらをご覧ください: 優れたAPIを設計する方法とそれが重要な理由
「静的vsインスタンス」メソッドの説明とは直接関係ありませんが、API設計の興味深い点に触れています。
静的メソッドを持つことに関する1つの問題は、オブジェクトを単体テストで使用するのがより難しくなる可能性があることです。 Mockitoは静的メソッドのモックを作成できず、メソッドのサブクラス実装を作成できません。
メソッドが基本的に、予測可能な状態情報を決して使用しないサブルーチンである場合、静的に宣言します。
これにより、他の静的メソッドまたはクラスの初期化で使用できます。
public class Example {
//...
//Only possible if computeOne is static
public final static double COMPUTED_ONE = computeOne(new Something("1"));
//...
}
このような場合の私の好みは、computeOne
およびcomputeMore
静的メソッドを作成することです。理由:カプセル化。クラスの実装にアクセスできるコードが少ないほど良いです。
あなたが与える例では、computeOne
とcomputeMore
はクラスの内部にアクセスする必要がないと述べているので、クラスのメンテナーが内部に干渉する機会を与えてください。
他のポスターが間違った情報を与えていると言っているいくつかのことを明確にしたいと思います。
まず、メソッドは静的であると宣言してもプライベートであるため、このクラスの外部からアクセスすることはできません。第二に、これらはプライベートであるため、サブクラスでオーバーライドすることさえできないため、静的または非静的によって違いは生じません。第三に、非静的なプライベートメソッドは、クラスのコンストラクターからも呼び出すことができ、静的である必要はありません。
ここで、プライベートヘルパーメソッドを静的または非静的として定義する必要があるかどうかについて質問します。プライベートメソッドを静的としてマークすると、コーディング時にこのルールに従うため、このメソッドはステートレスであることを示すため、Steveの回答に進みます。
経験から、私はそのようなプライベートな方法は非常に普遍的で再利用可能である傾向があると述べます。
私が最初にすべきことは、メソッドが現在のクラスコンテキスト以外でも役立つかどうかを質問することだと思います。もしそうなら、私はEveryoneが提案することを正確に行い、このメソッドをいくつかのutilsクラスに静的として抽出します。
このような一般的な使用のプライベートメソッドは、各開発者が使用する必要がある場所で独自に再発明するため、プロジェクトのコード複製の大部分を占めています。そのため、このような方法を集中化するのが方法です。
静的/非静的の質問は、「本当にこのクラスのオブジェクトを使用する必要があるか」になりますか?
だから、異なるメソッド間でオブジェクトを渡しますか?オブジェクトには、静的メソッドのコンテキスト外で役立つ情報が含まれていますか?メソッドを両方の方法で使用する場合、両方の方法でメソッドを定義しない理由はありますか?
このジレンマに陥っているのであれば、メソッドに必要なすべてのデータがオブジェクトの外部のコードに浮かんでいるように思えます。これは、あなたの望むことですか?毎回そのデータを常にオブジェクトに収集する方が簡単でしょうか?単一のモデルにコミットすることについて、あいまいなだけかもしれません。すべてを1つの方法で実行できる場合は、静的または非静的のいずれかを選択して、それを使用します。
より具体的には、これらのメソッドを定義する目的は、機能よりもコードを読みやすくすることの方が目的のようです(これらはare privateとして定義されています)。その場合、静的の目的はクラスの機能を公開することなので、静的を使用しても実際には何も起こりません。
class Whatever {
public static varType myVar = initializeClassVariable();
private static varType initializeClassVariable() {
//initialization code goes here
}
}
プライベートスタティックメソッドの利点は、クラス変数を再初期化する必要がある場合に後で再利用できることです。
理由の1つは、他のすべてが等しい場合、静的メソッド呼び出しが高速になるはずだということです。静的メソッドは仮想にすることはできず、暗黙のこの参照を取得しません。
Static修飾子がなければ、メソッドを(再)作成するときに簡単に実行できる追加の分析なしでは、メソッドがステートレスであることを理解できません。
次に、「静的」修飾子を使用すると、他の人が役に立たない他の要素に加えて、リファクタリングに関するアイデアを得ることができます。例えば。メソッドをユーティリティクラスに移動するか、メンバーメソッドに変換します。
オフトピック:静的メソッドのみを含むスタンドアロンユーティリティ/ヘルパークラスにヘルパーメソッドを保持します。
使用時にヘルパーメソッドを使用する場合の問題(「同じクラス」と読みます)は、誰かが同じ場所に無関係のヘルパーメソッドを投稿することを選択する可能性があることです。
それらを静的として宣言し、ステートレスとしてフラグを立てます。
Javaには、エクスポートされないマイナー操作のための優れたメカニズムがないため、プライベートスタティックは許容できると思います。
多くの人が言ったように、それをstatic!私が従う経験則は次のとおりです。メソッドが単なる数学関数であると考える場合、つまり、ステートレスであり、インスタンス変数を含まない(= >メソッドには青い変数がない(Eclipseで))、メソッドの結果は 'n'回の呼び出し(同じパラメーター、もちろん)で同じになり、そのメソッドをSTATICとしてマークします。
そして、このメソッドが他のクラスに役立つと思われる場合は、それ以外の場合はUtilクラスに移動し、同じクラスにメソッドをプライベートとして配置します。 (アクセシビリティの最小化)