web-dev-qa-db-ja.com

内部参照を公開しないjava.util.Dateのクローンまたはコピー

オブジェクト(エンティティ)の内部参照を公開しないことをお勧めします。したがって、オブジェクトに_Java.util.Date_型のフィールドがある場合、このフィールドのゲッターは元の日付ではなく、そのコピー。

しかし、Java.util.Dateの場合、そのコピーを作成する2つの一般的な方法があります。

  • クローン:_(Date) originalDate.clone()_
  • コンストラクターnew Date(originalDate.getTime())を介してコピー

私の質問は、どちらの方が良いですか、そしてなぜですか?

64
Ralph

間違いなくDateであれば、どちらの方法でも違いはありません。

実際のオブジェクトがDateサブクラス(_Java.sql.Date_など)である場合、clone()は追加情報(クラスを含む)を保持しますが、コンストラクターの呼び出しは保持しません。

余談ですが、 Joda Time を使用した場合、使用する不変型がたくさんあるため、この問題は発生しません。また、はるかに優れたAPIです:)

43
Jon Skeet

読み取り 有効なJava 。コピーを作成する好ましい方法は、コピーコンストラクターアプローチを使用することです。

Bill Venners:本では、Cloneableを実装してクローンを作成する代わりに、コピーコンストラクターを使用することをお勧めします。それについて詳しく説明していただけますか?

Josh Bloch:もしあなたが私の本の中でクローンについての項目を読んだなら、特に行間を読んでいるなら、クローンが深く壊れていると思うでしょう。設計上の欠陥がいくつかありますが、その最大のものは、Cloneableインターフェースにcloneメソッドがないことです。そして、それは単に機能しないことを意味します。Cloneableを作成しても、それで何ができるかについては何も言いません。代わりに、内部的に何ができるかについて述べています。 super.cloneを繰り返し呼び出すことによりObjectのcloneメソッドを呼び出すことになった場合、このメソッドは元のフィールドコピーを返すと言います。

35
Amir Afghani

防御的にコーディングする場合は、コピーコンストラクターが必要になります。 Effective Javaからのこの文章 を参照してください:

また、防御的なコピーを作成するためにDateのcloneメソッドを使用しなかったことにも注意してください。 Dateは最終ではないため、cloneメソッドは、クラスがJava.util.Dateであるオブジェクトを返すことを保証されていません。悪意のあるいたずらのために特別に設計された信頼できないサブクラスのインスタンスを返す可能性があります。このようなサブクラスは、たとえば、作成時にプライベート静的リストに各インスタンスへの参照を記録し、攻撃者がこのリストにアクセスできるようにする可能性があります。これにより、攻撃者はすべてのインスタンスを自由に支配できます。この種の攻撃を防ぐには、クローンメソッドを使用して、信頼できない関係者がサブクラス化できるタイプのパラメーターの防御コピーを作成しないでください。

15
robpvn