質問

最近Javaを読んでいて、新しいこと(イディオム?)に出会いました。プログラムでは、複数のコンストラクターを持つクラスには常に空のコンストラクターも含まれます。例:

public class Genotype {
  private boolean bits[];
  private int rating;
  private int length;
  private Random random;

  public Genotype() {              //  <= THIS is the bandit, this one right here
    random = new Random();
  }

  /* creates a Random genetoype */
  public Genotype(int length, Random r) {
    random = r;
    this.length = length;
    bits = new boolean[length];

    for(int i=0;i<length;i++) {
        bits[i] =random.nextBoolean();
    }
  }

  /* copy constructor */
  public Genotype(Genotype g,Random r) {
    random = r;
    bits = new boolean[g.length];
    rating = g.rating;
    length = g.length;

    for(int i=0;i<length;i++) {
        bits[i] = g.bits[i];
    }

  }
}

最初のコンストラクターは&quot; real&quot;ではないようですコンストラクタでは、すべての場合に他のコンストラクタのいずれかが使用されるように見えます。では、なぜそのコンストラクターが定義されているのですか?

役に立ちましたか?

解決

あなたが読んでいたコードが高品質であったかどうかはわかりません(過去にいくつかのバイオインフォマティクスコードをレビューしましたが、残念なことにプロの開発者によって書かれていないことがよくあります)。たとえば、3番目のコンストラクターはコピーコンストラクターではなく、一般にこのコードに問題があるため、「あまり読みすぎないでください」。

最初のコンストラクターはデフォルトのコンストラクターです。最低限の初期化のみを行い、ユーザーがゲッターとセッターで残りを設定できるようにします。多くの場合、他のコンストラクターは「便利なコンストラクター」です。少ない呼び出しでオブジェクトを作成するのに役立ちます。ただし、これは多くの場合、コンストラクター間の不整合につながる可能性があります。実際、セッターへの後続の呼び出しを伴うデフォルトのコンストラクターが望ましいことを示す最近の研究があります。

デフォルトのコンストラクターが重要な場合もあります。たとえば、ダイジェスターのような特定のフレームワーク(XMLから直接オブジェクトを作成するために使用)は、デフォルトのコンストラクターを使用します。 JavaBeansは一般にデフォルトのコンストラクターなどを使用します。

また、一部のクラスは他のクラスから継承します。親オブジェクトの初期化が「十分」である場合、デフォルトのコンストラクターが表示される場合があります。

この特定の場合、そのコンストラクタが定義されていない場合、事前にすべての詳細を知る必要があります。それは常に望ましいとは限りません。

そして最後に、一部のIDEはデフォルトのコンストラクタを自動的に生成します。クラスを書いた人は誰でもクラスを削除することを恐れていた可能性があります。

他のヒント

オブジェクトはシリアル化可能

  

非直列化可能クラスのサブタイプを直列化できるようにするために、サブタイプはスーパータイプのパブリック、保護、および(アクセス可能な場合)パッケージフィールドの状態を保存および復元する責任を負います。サブタイプは、拡張するクラスにクラスの状態を初期化するためのアクセス可能な引数なしのコンストラクタがある場合にのみ、この責任を引き受けることができます。そうでない場合、クラスSerializableを宣言するとエラーになります。エラーは実行時に検出されます。

     

逆シリアル化中、非シリアル化可能なクラスのフィールドは、クラスのpublicまたはprotected no-argコンストラクターを使用して初期化されます。引数なしのコンストラクターは、シリアル化可能なサブクラスからアクセス可能でなければなりません。シリアル化可能なサブクラスのフィールドは、ストリームから復元されます

はい、「空白」に同意します。コンストラクタは常に存在する必要はありません(私の経験では、初心者はしばしばこの間違いを犯します)。ただし、空のコンストラクタで十分な場合もあります。ただし、空のコンストラクターが、構築後にすべてのメンバーが適切にインスタンス化されるという不変条件に違反する場合は、空のコンストラクターを使用しないでください。コンストラクターが複雑な場合は、構築をいくつかのprotected / privateメソッドに分割することをお勧めします。次に、必要に応じて、 static メソッドまたは別の Factory クラスを使用して、構築のために保護されたメソッドを呼び出します。

上で書いたことは理想的なシナリオです。ただし、springのようなフレームワークは、コードからいくつかのxml構成ファイルにコンストラクターロジックを削除します。ゲッターおよびセッター関数を使用できますが、おそらくインターフェイスここで説明されているとおり

デフォルトのコンストラクターは必須ではありません。

クラスにコンストラクターが定義されていない場合、デフォルトの(空の)コンストラクターが自動的に作成されます。パラメーター化されたコンストラクターを提供した場合、デフォルトのコンストラクターは自動的に作成されないため、自分で作成することをお勧めします。実行時に依存性注入と動的プロキシ作成を使用するフレームワークでは、通常、デフォルトのコンストラクターが必要です。したがって、作成するクラスのユースケースに依存します。

デフォルトのコンストラクターは、機能的なビューには適していません。 オブジェクトにメソッドのグローバルな可視性がある場合は、デフォルトのコンストラクターが使用されます。たとえば、オブジェクトの実際の状態をtry / catchに記録する場合 コーディングできます

MyObejct myObject=null
try{...
}catch(Exception e){
    log.error(myObject);//maybe print null. information?
}

またはあなたが好きですか

MyObejct myObject=new Object();
try{...
}catch(Exception e){
log.error(myObject);//sure print  myobject.toString, never null. More information
}

別の方法でEMPTYオブジェクトを作成するロジックはそれほど多くありませんが、NULLオブジェクトをインスタンス化することは私の意見では有害です。 この投稿

これはコピーコンストラクターではありません。基本的に、何らかのフレームワークを使用する場合は、空のコンストラクターが必要です。もちろん、パブリックまたはプライベートの空のコンストラクターが常に存在する必要がありますが、少なくとも、クラスのインスタンス化方法(またはインスタンス化されていない方法)を制御できます。

通常、オブジェクトを完全に初期化するコンストラクターを1つ作成します。他に存在する場合、それらはすべて適切なデフォルトでthis(...)を呼び出します。

オブジェクトは100%初期化され、作成時に使用できる状態になっている必要があります。

Hibernateなどの一部のフレームワークでは、引数なしのコンストラクタが必要です。彼らがベストプラクティスと衝突する方法は、時々私を不安にさせます。

デフォルトの空の(空白の)コンストラクターを使用すると、最終フィールドを使用できなくなります。これは、多くの場合、必要のない多くの可変性をもたらします。

ビルダーパターンを使用すると、これら2つのスタイルを混在させることができ、ファクトリの背後に多引数コンストラクターを非表示にすることで不変性を維持しながら、より柔軟な初期化が可能になります。

一部のPOJOクラスまたは単純なクラスでは、デフォルトのコンストラクターを使用して、クラスでユニットテストを実行する場合があります。それらをモックする必要はありません。デフォルトのコンストラクタでオブジェクトを新規作成し、値セットをテストして取得するか、引数として渡すことができます。

これを拡張したクラスの空のコンストラクタを作成したい クラスとそれがクラスを拡張しているので...子には、親より上のクラスを参照するスーパーがあります。子がsuper(stuff)を指定しなかった場合...使用する他のコンストラクターを参照するための内部のものは、空のコンストラクターを参照しようとします。

エラーがどうなるかわかりません。最初の親オブジェクトの関係を今コーディングしているので、ここで物事を探していました。

空のコンストラクタではないコンストラクタを作成して、デフォルトの空のコンストラクタを失う瞬間を追加する必要があると思います。そのため、拡張クラスのデフォルトであるsuper()は指すものがありません。もちろん、デフォルトのsuper()を削除するものを指定することでsuperの世話をする拡張クラスを作成した場合、これを回避しますが、誰かがあなたのクラスを使用して拡張し、そこから拡張し、そこに気づいていない場合あなたが持つことができるときに空のセット 作成したばかりです。

これは私の最初の投稿ですが、私がそれを理解する方法から亀裂を取りたかったです。

scroll top