3

これはEffective Javaでの防御コピーの例です。私の根底にある質問のシナリオには防御的なコピーが必要であり、渡されたオブジェクトの変更を避けるようにクライアントに要求するコメントには対応できないと仮定します。

public Period(Date start, Date end) {
    this.start = new Date(start.getTime());
    this.end = new Date(end.getTime());
}

質問:

  1. Date自分自身をより一般的にするために、自分自身を取り込むコンストラクターがなく、オブジェクトが渡され、それ自体を複製するメカニズムがなく、そのようなオブジェクトが私たちに属していない場合、つまり、変更できない場合はどうすればよいですか?

  2. コンストラクターが型パラメーターを引数として取りPeriod(T object)、T が変更可能である可能性があるため、防御コピーが必要な場合はどうなりますか。Tが何であるかはわかりません。この場合、防御的コピーを行うにはどうすればよいですか?

  3. Date一部のサブクラスにはそれ自体のオブジェクトを作成するようなコンストラクターがあり、一部のサブクラスにはそうするメカニズムがない場合に渡されるインターフェイスとは何ですか?

  4. どのくらいの深さまで防御的にコピーする必要がありますか? 配列をコピーするとしましょうが、配列要素は変更可能でしたか?

4

3 に答える 3

2
  1. すべての状態が利用可能な場合、その状態を抽出して、自分で新しいオブジェクトを構築できます。それ以外の場合は、厄介なリフレクションまたはシリアル化のトリックを使用する以外に何もできません。
  2. T が自分自身をコピーできるクラスのインスタンスでない場合、何もできません。
  3. あなたはそれについて何もできません。
  4. 場合によります。

あなたの質問を読むと、「防御コピー」のアドバイスをあらゆる場所に適用したいと思われます。すべきではありません。ほとんどの場合、ミュータブル オブジェクトを使用するコードでは、コピーではなく、元のオブジェクトへの参照が必要です。特に、引数として取得するものが抽象クラスまたはインターフェースのインスタンスである場合。

Date は可変であってはならない可変値型であり、適切に設計されていればそうならないため、Date の防御的なコピーを作成する必要があります。値型の不変性を促進すると、防御コピーは不要になります。非値型の場合、通常はコピーではなく、オブジェクトへの参照が必要です。

于 2014-01-09T08:11:15.933 に答える
0
  1. とにかくオブジェクトの状態を変更できない場合は、防御コピーは必要ありません。
  2. あなたができる唯一のことは、 T の実装の可能性を想定し、それらをinstanceOfでチェックすることです。
  3. 2と同じ。
  4. あなたの裁量で。配列要素を変更すると別の場所でプログラムが壊れる可能性があると思われる場合は、それらもすべてコピーする必要があります。
于 2014-01-09T08:25:00.847 に答える
0

メソッドに渡すオブジェクトが変更可能な場合、防御的プログラミングが重要になります。(Effective Java ブックでも説明されている) 良い方法は、それらを不変にすることです。

  1. Date クラスが final でない場合は、Date のサブクラスであるラッパー クラスを作成できます。
  2. 場合によります。おそらく、クローンを作成する必要はありません。
  3. 気にする必要はありません。インターフェイスの実装者は、同期の問題に対処する必要があります。一般に、実装ではなくインターフェイスを渡すことをお勧めします。
  4. 標準の Java コレクションの場合、java.util.Collections クラスには、unmodifiableList や unmodifiableMap など、防御的プログラミングに使用することを目的とした多くのユーティリティ メソッドがあります。
于 2014-01-09T08:26:46.450 に答える