web-dev-qa-db-ja.com

Javaのコンストラクタは非公開にできますか?

コンストラクタは非公開にできますか?プライベートコンストラクタはどのように便利ですか?

210
Rajesh

はい、コンストラクタはプライベートにすることができます。これにはさまざまな用途があります。そのような用途の1つは、 シングルトンデザインアンチパターン です。私はあなたに対して使うことを忠告します。もう1つの、より正当な用途は、コンストラクターを委任することです。 1つのコンストラクタを持つことができますが、それは実際には実装の詳細であり、さまざまなオプションがあります。したがって、それを非公開にしますが、残りのコンストラクタはそれに委任します。

次のクラスでは、コンストラクタの委任の例として、値と型を保存できますが、型のサブセットに対してのみ実行できます。そのため、許可された型のみを使用するには、一般コンストラクタを非公開にする必要があります。 。共通のプライベートコンストラクタはコードの再利用を助けます。

public class MyClass {
     private final String value;
     private final String type;

     public MyClass(int x){
         this(Integer.toString(x), "int");
     }

     public MyClass(boolean x){
         this(Boolean.toString(x), "boolean");
     }

     public String toString(){
         return value;
     }

     public String getType(){
         return type;
     }

     private MyClass(String value, String type){
         this.value = value;
         this.type = type;
     }
}

編集する
数年後のこの答えを見て、私はこの答えが不完全であると同時に少し極端でもあることに注目したいと思います。シングルトンは確かにアンチパターンであり、一般的に可能な限り避けるべきです。しかし、シングルトン以外にもプライベートコンストラクタの使い方がたくさんあり、私の答えは1つだけです。

プライベートコンストラクタが使用されている場合をさらにいくつか挙げます。

  1. 関連する静的関数の単なる集合である実体のないクラスを作成するには(これは基本的にシングルトンですが、それがステートレスで静的関数がクラス状態ではなくパラメータに厳密に作用する場合、これは私のように不合理な方法ではありません)実装に多数の依存関係や他の形式のコンテキストが必要な場合は、依存性が注入されたインターフェイスを使用するとAPIの保守が容易になることがよくありますが、以前の自己が示唆するように思われます。

  2. オブジェクトを作成する方法が複数ある場合は、プライベートコンストラクタを使用すると、さまざまな方法でオブジェクトを簡単に理解できます(たとえば、new ArrayList(5)ArrayList.createWithCapacity(5)ArrayList.createWithContents(5)ArrayList.createWithInitialSize(5)など)。つまり、プライベートコンストラクタを使用すると、名前がわかりやすいファクトリ関数を提供することができ、コンストラクタをプライベートにすることで、より自明な名前だけを使用できます。これは ビルダーパターン でもよく使われます。例えば:

    MyClass myVar = MyClass
        .newBuilder()
        .setOption1(option1)
        .setOption2(option2)
        .build();
    
144

誰かがこれに言及していることを期待していましたが(2点目)、..プライベートコンストラクタの用途は3つあります。

  • 次のような場合に、オブジェクトの外部でインスタンス化されないようにします。

    • シングルトン
    • 工場メソッド
    • 静的メソッド専用(ユーティリティー)クラス
    • 定数のみのクラス
      .
  • sublcassing(拡張)を防ぐために。プライベートコンストラクタだけを作成した場合、クラスはsuper()コンストラクタを呼び出すことができないため、クラスを拡張することはできません。これはfinalの一種の同義語です。

  • オーバーロードされたコンストラクタ - メソッドやコンストラクタをオーバーロードした結果として、プライベートになったり、パブリックになったりすることがあります。特に、コンストラクタで使用する非パブリッククラスがある場合は、そのクラスのインスタンスを作成し、それをプライベートコンストラクタに渡すパブリックコンストラクタを作成できます。

90
Bozho

はい、できます。プライベートコンストラクタは、クラスがインスタンス化されるのを防ぐために、または構築が内部的にのみ行われるために存在します。 Factoryパターン詳しくは ここ を参照してください。

24
Feanor

はい。

これは、クラスのインスタンス化方法を制御できるようにするためです。コンストラクタを非公開にしてからクラスのインスタンスを返す表示可能なコンストラクタメソッドを作成すると、作成数を制限する(通常はインスタンスが1つだけであることを保証する)、インスタンスやその他の構築関連タスクのリサイクルなどができます。 。

new x()を実行してもnullが返されることはありませんが、ファクトリパターンを使用してnullを返すことも、さまざまなサブタイプを返すこともできます。

また、ユーティリティ関数クラスのように、インスタンスメンバやプロパティを持たないクラス(静的なものだけ)にも使用できます。

16
lavinio

クラス内のすべてのメソッドが静的な場合は、プライベートコンストラクタを使用することをお勧めします。

9
lichenbo

以下の理由で、プライベートコンストラクタはJavaで定義できます。

  1. Javaオブジェクトのインスタンス化を制御するために、オブジェクトのインスタンスを作成することはできません。

  2. クラスをサブクラス化することはできません

  3. これは、singleton Patternを実装するときに特別な利点があります。これにはPrivateコンストラクタが使用され、アプリケーション全体のインスタンスの作成を制御できます。

  4. すべての定数を定義したクラスを作成し、そのインスタンスをもう必要としない場合は、そのクラスをプライベートコンストラクタとして宣言します。

6
gmhk

はい。

Javaで使用するMath finalクラスなど、プライベートコンストラクタはインスタンスの初期化を防ぐために使用されます。シングルトンもプライベートコンストラクタを使う

5
ryf9059

はい。クラスはプライベートコンストラクタを持つことができます。抽象クラスでもプライベートコンストラクタを持つことができます。

コンストラクタを非公開にすることで、クラスがインスタンス化されたり、そのクラスがサブクラス化されたりするのを防ぎます。

これがプライベートコンストラクタの使い方の一部です。

  1. シングルトンデザインパターン
  2. インスタンス作成数を制限する
  3. 静的ファクトリメソッドを使用してオブジェクト作成に意味のある名前を付ける
  4. 静的ユーティリティクラスまたは定数クラス
  5. サブクラス化を防ぐため
  6. ビルダーデザインパターン したがって、 不変クラスの作成
4
Abhi Andhariya

はい、クラスはプライベートコンストラクタを持つことができます。他のクラスからコンストラクターにアクセスすることを禁止し、定義済みクラス内からアクセスできるようにするために必要です。

なぜあなたはあなたのクラスのオブジェクトを内部的にのみ作成したいのですか?これは何らかの理由で実行できますが、考えられる理由の1つは、シングルトンを実装することです。シングルトンは、クラスのインスタンスを1つだけ作成できるようにするデザインパターンです。これは、プライベートコンストラクタを使用して実現できます。

3
SBTec

はい。インスタンス化やその後の上書きを防ぐために使用されます。これはシングルトンクラスで最もよく使われます。

2
Vaishak Suresh

はい、コンストラクタはプライベートにすることができます。プライベートコンストラクタは、他のクラスがプライベートコンストラクタの例をインスタンス化するのを防ぎます。

public class CustomHttpClient {
private static HttpClient customHttpClient;

/** A private Constructor prevents any other class from instantiating. */
private CustomHttpClient() {
}}
2
jai_b

プライベートコンストラクタは、クラスが呼び出し側によって明示的にインスタンス化されるのを防ぎます PrivateConstructor に関するさらなる情報を参照してください。

1
GustyWind

コンストラクタは非公開にできますか?プライベートコンストラクタはどのように便利ですか?

はい、できます。私はそれが有用であることのもう一つの例を考えます:

//... ErrorType.Java
public enum ErrorType {
    X,
    Y,
    Z
}

//... ErrorTypeException.Java
import Java.util.*;
import Java.lang.*;
import Java.io.*;

//Translates ErrorTypes only
abstract public class ErrorTypeException extends Exception {
    private ErrorTypeException(){}

    //I don't want to expose thse
    static private class Xx extends ErrorTypeException {}
    static private class Yx extends ErrorTypeException {}
    static private class Zx extends ErrorTypeException {}

    // Want translation without exposing underlying type
    public static Exception from(ErrorType errorType) {
        switch (errorType) {
            case X:
                return new Xx();    
            case Y:
                return new Yx();
            default:
                return new Zx();
        }
    }

    // Want to get hold of class without exposing underlying type
    public static Class<? extends ErrorTypeException> toExceptionClass(ErrorType errorType) {
        switch (errorType) {
            case X:
                return Xx.class;    
            case Y:
                return Yx.class;
            default:
                return Zx.class;
        }
    }
}

上記の場合、抽象クラスが静的な内部クラス以外の派生クラスによってインスタンス化されるのを防ぎます。抽象クラスは最終的にはできませんが、この場合、privateコンストラクタは内部クラスではないすべてのクラスに対して実質的に最終的なものにします。

1
Werner Erasmus

私によれば、コンストラクタをプライベートとして宣言することができ、また、コンストラクタを宣言してからクラスオブジェクトを返すクラス内の静的メソッドを使用することによって、サブクラス内のそのクラスのインスタンスを取得できます。 classname.method name bczを使用してこのメ​​ソッドをサブクラスにクラス分けします。これは静的メソッドであり、constを宣言するclassのインスタンスを取得します。

0
user3391823

プライベートコンストラクタを持つことの背後にある基本的な考え方は、JVMによって外部からのクラスのインスタンス化を制限することですが、引数コンストラクタを持つクラスであれば、意図的にインスタンス化していると推測します。

0
Phani