javaのクローンメソッドとコピーコンストラクタ。どちらが正しい解決策です。各ケースの使用場所
クローンが壊れているので、使用しないでください。
ObjectクラスのCLONEメソッドは、純粋なJavaメソッドでは不可能だった、やや魔法的なメソッドです。オブジェクトの同一のコピーを生成します。 Javaコンパイラ*のベータリリース日以降、プリミティブオブジェクトスーパークラスに存在していました。そして、それは、すべての古代の魔法と同様に、スペルが予期せずバックファイアするのを防ぐために適切な呪文を必要とします
オブジェクトをコピーするメソッドを優先する
Foo copyFoo (Foo foo){
Foo f = new Foo();
//for all properties in FOo
f.set(foo.get());
return f;
}
続きを読む http://adtmag.com/articles/2000/01/18/effective-javaeffective-cloning.aspx
clone()
はそのままでは機能しないことに注意してください。 Cloneable
を実装し、public
で作成するclone()
メソッドをオーバーライドする必要があります。
いくつかの選択肢がありますが、それは望ましいものです(他の回答で述べられているように、clone()
メソッドには多くの設計上の問題があるため)。
BeanUtils.cloneBean(original)
は、Object.clone()
によって作成されたような浅いクローンを作成します。 (このクラスは commons-beanutils からのものです)
SerializationUtils.clone(original)
は、深いクローンを作成します。 (つまり、最初のレベルだけでなく、プロパティグラフ全体が複製されます)( commons-lang から)が、すべてのクラスはSerializable
を実装する必要があります
Java Deep Cloning Library は、Serializable
を実装する必要なく、ディープクローニングを提供します。
clone()は、いくつかの間違いで設計されました( この質問 を参照)。したがって、避けるのが最善です。
有効なJava第2版 、項目11:クローンを慎重にオーバーライドする
Cloneableに関連するすべての問題を考えると、他のインターフェイスはCloneableを拡張すべきではなく、継承用に設計されたクラス(項目17)はCloneableを実装すべきでないと言っても安全です。多くの欠点があるため、一部のエキスパートプログラマは、配列をコピーする場合を除いて、cloneメソッドをオーバーライドせず、cloneメソッドを呼び出さないことを選択します。継承用のクラスを設計する場合、適切に保護されたcloneメソッドを提供しないことを選択した場合、サブクラスがCloneableを実装できないことに注意してください。
この本では、コピーコンストラクターがCloneable/cloneよりも優れている点についても説明しています。
すべての標準コレクションには、コピーコンストラクターがあります。それらを使用します。
List<Double> original = // some list
List<Double> copy = new ArrayList<Double>(original);
コピーコンストラクターは、クラスタイプをコピーコンストラクターのクラスタイプに制限することに注意してください。例を考えてみましょう:
// Need to clone person, which is type Person
Person clone = new Person(person);
person
がPerson
のサブクラスになり得る場合(またはPerson
がインターフェースの場合)、これは機能しません。これがクローンのポイントです。実行時に適切な型を動的にクローンできるということです(クローンが適切に実装されていると仮定します)。
Person clone = (Person)person.clone();
または
Person clone = (Person)SomeCloneUtil.clone(person); // See Bozho's answer
person
が適切に実装されていると仮定すると、Person
にはclone
の任意のタイプを指定できます。
参照: クローンメソッドを適切にオーバーライドする方法? 。 Javaでのクローンは壊れています。それを正しくするのはとても難しいであり、それを行う場合でもそれほど多くは提供しませんなので、本当に面倒な価値はありません。
悲しみ:Cloneable/cloneもコンストラクタも素晴らしい解決策ではありません:実装クラスを知りたくない!!! (たとえば、同じ隠しMumbleMap実装を使用して、コピーしたいMapがあります)コピーが必要な場合は、コピーを作成したいだけです。しかし、残念ながら、Cloneableにはcloneメソッドがありません。そのため、clone()を呼び出すために安全に型キャストできるものはありません。
最高の「オブジェクトのコピー」ライブラリが何であれ、Oracleはそれを次のJavaリリースの標準コンポーネントにする必要があります(既に存在しない場合はどこかに隠されています)。
もちろん、より多くのライブラリ(たとえば、コレクション)が不変である場合、この「コピー」タスクはなくなります。しかし、その後、verdammt「bean」パターンではなく「class invariants」のようなものを使用してJavaプログラムの設計を開始します(壊れたオブジェクトを作成し、[十分]になるまで突然変異させます)。