web-dev-qa-db-ja.com

java)でクラスをインスタンス化することは避けてください

最近、私は質問に直面しました:Javaクラスのインスタンス化を回避する方法は?

しかし、私は次のように答えました。

  1. クラスをインスタンス化したくない場合は、「abstract」修飾子を使用してください。例:javax.servlet.HttpServletは、インスタンス化を回避するために抽象として宣言されています(ただし、そのメソッドはいずれも抽象ではありません)。

  2. 引数なしのプライベートコンストラクターを宣言します。

今私の質問はa)他の方法はありますか? b)なぜ誰もがクラスをインスタンス化したくないのですか? --SOで検索した後、 this から、Utilクラスをインスタンス化しないようにすることができることを知りました。 OOPでクラスをインスタンス化したくない他の場所はありますか?

18
jai

4つの理由が思い浮かびます。

  1. サブクラスを許可しますが、親はインスタンス化できません。
  2. directインスタンス化を禁止し、代わりにファクトリメソッドを提供して戻り、必要に応じてインスタンスを作成します。
  3. Java 5なので、代わりにタイプセーフ列挙型が推奨されますが、すべてのインスタンスが事前定義されているため(たとえば、トランプのスート)。
  4. クラスは実際にはクラスではありません。これは、静的定数やメソッドの単なるホルダーです。

(2)の例として、正規のオブジェクトを作成することができます。たとえば、RGBの色の組み合わせ。 RGBコンボのインスタンスを複数作成したくないので、次のようにします。

public class MyColor {
  private final int red, green, blue;

  private MyColor(int red, int green, int blue) {
    this.red = red;
    this.green = green;
    this.blue = blue;
  }

  public static MyColor getInstance(int red, int green, int blue) {
    // if combo already exists, return it, otherwise create new instance
  }
}

注:別のコンストラクターが明示的に定義されているため、引数なしのコンストラクターは必要ありません。

26
cletus

実際にはあなたの質問に対する答えではなく、ただのメモです:

ユーティリティクラスのインスタンス化を防ぐために引数なしのプライベートコンストラクタを作成する場合は、コンストラクタに例外(UnsupportedOperationExceptionなど)をスローさせる必要があります。これは、リフレクションを介して実際にプライベートメンバー(コンストラクターを含む)にアクセスできるためです。クラスをpreventするコンストラクターを定義するのは少し直感に反するため、そうする場合はコメントを付ける必要があることに注意してください。インスタンス化されることから。

ユーティリティクラスを抽象化すると、クラスが拡張されることを意図しているように見えるため、お勧めできません。さらに、クラスを拡張してインスタンス化することもできます。

10
Kolibri

既存のすべてのインスタンスを完全に制御するために、他のユーザーがオブジェクトをインスタンス化するのを避けたい場合があります。一例は シングルトンパターン です。

3
Zed

クラスをインスタンス化したくない最も一般的な理由は、静的クラス、つまり静的メソッドを扱っているときだと思います。誰かがそのクラスをインスタンス化しようとするのは望ましくありません。同様に、Factoryクラスを処理している場合、または場合によっては、多くのシングルトンクラスは、通常の方法でインスタンス化されないようにコンストラクターを非表示にします。

2
jW.

クラスをインスタンス化できないようにする別の方法は、それをプライベート内部クラスとして宣言し、それを周囲のクラスでインスタンス化する方法を提供しないことです。しかし、これは(IMO)かなり無意味です。

クラスをインスタンス化する意味がない場合は、クラスをインスタンス化できないようにする必要があります。通常、クラスが実際には(静的)ヘルパーメソッドのコレクションにすぎない場合、またはクラスが「不完全」である場合にこれを行います。不完全性は構文的に明らかである可能性があります(つまり、抽象メソッド)が、他の種類の不完全性があります。たとえば、すべてのメソッドにデフォルトのデフォルト実装を提供し、クラスが何か有用なことを行うために、それらの1つ以上をオーバーライドする必要がある場合があります。

クラスをインスタンス化できない(または少なくとも直接インスタンス化できない)ようにするもう1つの理由は、アプリケーションがインスタンス化を制御する必要がある場合です。たとえば、Java.util.regex.Patternクラスを直接インスタンス化して、JREがコンパイル済みの正規表現のキャッシュを維持できるようにすることはできません。

1
Stephen C