Java:静的クラス?


130

ユーティリティ関数がいっぱいのクラスがあります。そのインスタンスをインスタンス化しても意味がありませんが、そのメソッドを呼び出したいと思います。これに対処する最良の方法は何ですか?静的クラス?概要?


14
ところで、トップレベルのクラスを静的にすることはできません...
Jon

回答:


163

finalとマークされたクラスのプライベートコンストラクターと静的メソッド。


19
@matt b:David Roblesが彼の答えで指摘しているように、クラスをfinalにする必要はありません...サブクラスはプライベートであるため、スーパークラスコンストラクターを呼び出すことができないため、サブクラス化できません。ただし...明示的にしても害はありません。しかしjfyi :-)。
トム

93

素晴らしい本によると、「効果的なJavaの」

項目4:プライベートコンストラクターでインスタンス化不能を強制する

-クラスを抽象化してインスタンス化不可能性を強制しようとしても機能しません。

-デフォルトのコンストラクターは、クラスに明示的なコンストラクターが含まれていない場合にのみ生成されるため、プライベートコンストラクターを含めることでクラスをインスタンス化できなくすることができます。

// Noninstantiable utility class
public class UtilityClass
{
    // Suppress default constructor for noninstantiability
    private UtilityClass() {
        throw new AssertionError();
    }
}

明示的なコンストラクターはプライベートであるため、クラスの外からはアクセスできません。AssertionErrorは厳密には必須ではありませんが、コンストラクターがクラス内から誤って呼び出された場合に備えて保証されます。これにより、どのような状況でもクラスがインスタンス化されないことが保証されます。このイディオムは、コンストラクターが明示的に提供されているため、呼び出せないため、少し直感に反しています。したがって、上記のようにコメントを含めるのが賢明です。

副作用として、このイディオムはクラスがサブクラス化されることも防ぎます。すべてのコンストラクターは、明示的または暗黙的にスーパークラスコンストラクターを呼び出す必要があり、サブクラスには、呼び出すアクセス可能なスーパークラスコンストラクターがありません。


1
なぜ選んだAssertionErrorのような他の選択肢を超えるIllegalStateExceptionUnsupportedOperationExceptionなど、?
Pacerier 2014年

@Pacerier これを見てください。
bcsb1001 2014年

@ bcsb1001、それは私たちにこれをもたらします。
パチェリエ

21

あなたはjava.lang.Mathに似たユーティリティクラスを持っているように聞こえます
そこでのアプローチは、プライベートコンストラクターと静的メソッドを備えた最終クラスです。

しかし、これはテスト容易化のために、私はこの記事を読んでお勧めしないものの用心
静的メソッドは、テスト容易に死です


では、java.lang.Mathは「テスト可能性への死」ですか?
Pacerier 2014年


6

上流を泳ぐためだけに、静的メンバーとクラスはOOに参加しないため、悪です。いいえ、悪ではありませんが、真剣に、アクセスにはシングルトンパターンの通常クラスをお勧めします。このようにして、将来的に動作をオーバーライドする必要がある場合でも、大きな改造ではありません。OOはあなたの友達です:-)

私の$ .02


17
シングルトンも悪と見なされます。
Dan Dyer、

3
プライベートコンストラクターを使用して、クラスがインスタンス化またはサブクラス化されるのを防ぎます。参照デビッド・ロブレス答え:stackoverflow.com/questions/1844355/java-static-class/...
ロブ

5
シングルトンは依存性注入よりも悪ではありません:)
評判の悪い2009

12
OOはその場所にありますが、それが実用的でない場合や、リソースの無駄になる場合があります。たとえば、Math.abs()のような単純なものです。オブジェクトをインスタンス化するためだけにオブジェクトをインスタンス化する理由はありません。静的メソッド呼び出しが、OOオーバーヘッドなしで同様に機能する場合です。;)
ロブ

2
@rob re OO、私は同意します、Math.Abs​​はおそらくインスタンスを必要としません。「ユーティリティクラスがあります」と聞くと、Math.Avg()が表示されます。ここで、加重平均のサポートを追加する必要があります。Urlジェネレーター、param in、url outを参照して、hrefをサポートするためにリファクタリングする必要がある、またはurlのみなどを表示します。これらの理由により、OOベースのユーティリティクラスを使用すると見返りが得られます。また、今度は標準のOO防御戦術、テストをドロップします!/ meアヒル
ベネットディル

3

「プライベートコンストラクタ」の引数についてコメントします。さあ、開発者はそれほど愚かではありません。しかし、彼らは怠惰です。オブジェクトを作成してから静的メソッドを呼び出しますか?起こりません。

クラスが誤用されないように、時間をかけすぎないようにしてください。同僚を信頼してください。クラスをどのように保護しても、クラスを誤用する方法が常にあります。悪用できないのは、まったく役に立たないことだけです。


7
(jsutの学生コードではなく、プロダクションコードで)object.staticMethodを見た人。あなたはジョーランダムプログラマーの能力を過大評価していると思います。:-P
TofuBeer

2
  • 最終クラスとプライベートコンストラクター(良いが必須ではない)
  • パブリック静的メソッド

1

クラスをとして宣言しても意味がありませんstatic。メソッドstaticを宣言して、JavaのMathクラスのように、通常どおりクラス名から呼び出すだけです。

また、コンストラクターをプライベートにする必要はありませんが、プライベートにすることをお勧めします。コンストラクターをプライベートにマークすると、他のユーザーがクラスのインスタンスを作成して、それらのインスタンスから静的メソッドを呼び出すことができなくなります。(これらの呼び出しはJavaでもまったく同じように機能しますが、誤解を招きやすく、コードの読みやすさに悪影響を及ぼします。)


1
また、プライベートコンストラクタを作成することを忘れないでください。
Asaph

@Asaph:そうですね。私は私の答えにそれを少し追加しました。ありがとう。
リザードを請求する

内部クラス内で静的メソッドが必要な場合は、クラスも静的でなければなりません。
Rui Marques

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