どのように書くでしょうか深いコピーオブジェクトにJava?
質問
Java奥高尾にひっそりと建つ料亭。を実行することが困難深いオブジェクトのコピー機能です。どのような手段で確保のためのオリジナルのクローニング株せん。
解決
安全な方法はserializeのオブジェクトを直列化復元).これにより、全ブランドの新しい参照です。
この記事 かいます。
注意:めることが可能で授業をオーバーライド直列化などの新しいインスタンスが ない 作成例のためのsingletons.またこのコースに動作しない場合には、授業な直列化可能です。
他のヒント
人数以上を使用、またはオーバーライド Object.clone()
.わからないないのである。 Object.clone()
いくつかの主要な問題、およびその利用することは勧められます。をご覧ください項目11から"有効なJava"によるジョシュア-ブロッホのための完全な答えです。ダウンロードいただけまを安全に利用できる Object.clone()
にプリミティブ型の配列が、それとは別に必要なものを堅約の適正使用をオーバークローン.
のスキームに直列化(XMLした場合にはkludgy.
あることは容易ではありませ答えます。したい場合は深いコピーオブジェクトまでトラバースのオブジェクトのグラフは、コピーを各子オブジェクトを明示的にオブジェクトのコピーコンストラクタまたはstaticファクトリメソッドで、深部の子オブジェクトです。Immutables例 String
う必要はありませんがコピーされます。ちなみに、好不変しました。
きの深いコピーとの直列化を行わずにファイルです。
御オブジェクトをご希望のディープコピーが必要 implement serializable
.場合にクラスな最終的にはできない変更、拡張するクラスを直列化可能です。
換されたクラスのストリームのバイト:
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(object);
oos.flush();
oos.close();
bos.close();
byte[] byteData = bos.toByteArray();
回復のクラスからバイトのストリーム:
ByteArrayInputStream bais = new ByteArrayInputStream(byteData);
(Object) object = (Object) new ObjectInputStream(bais).readObject();
まだ直列化に基づく深いクローンを用い org.apache.commons.lang3.SerializationUtils.clone(T)
Apache Commons Langるので注意が必要の性能が最悪でした。
ついては、一般的にベストプラクティスをお書き独自のクローンの方法を各クラスのオブジェクトのオブジェクトのグラフを必要とクローニング.
片道の実施に深くコピーが追加コピーコンストラクタを各関連するクラスです。コピーコンストラクタがインスタンスは"この単一の引数としてコピーの値からです。かなり作業が非常に簡単で安全です。
編集:はないことに注意してくださを利用する必要がアクセス用のメソッドを読みます。アクセスできるすべての分野に直接のソースインスタンスは常に同じタイプとしてのインスタンスのコピーコンストラクタです。明らかな可能性がある。
例:
public class Order {
private long number;
public Order() {
}
/**
* Copy constructor
*/
public Order(Order source) {
number = source.number;
}
}
public class Customer {
private String name;
private List<Order> orders = new ArrayList<Order>();
public Customer() {
}
/**
* Copy constructor
*/
public Customer(Customer source) {
name = source.name;
for (Order sourceOrder : source.orders) {
orders.add(new Order(sourceOrder));
}
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
編集:ご利用の場合コピーコンストラクタを知る必要があり実行時の型のオブジェクトではcopyingをご覧ください。上記のアプローチできません簡単にコピー複合リスト(ることができるかもしれませんで反射コードとします。
Apache commonsには、迅速に深いクローンのオブジェクトです。
My_Object object2= org.apache.commons.lang.SerializationUtils.clone(object1);
ができ 図書館 そのシンプルなAPIを行う比較的高速のクローニングとの反映と合わせることよりも早く直列化方法
Cloner cloner = new Cloner();
MyClass clone = cloner.deepClone(o);
// clone is a deep-clone of o
XStreamは本当に便利なう場合がございます。ここでは、簡単なコードなクローニング
private static final XStream XSTREAM = new XStream();
...
Object newObject = XSTREAM.fromXML(XSTREAM.toXML(obj));
一つなのでロジャクソンJSONをserialize複雑なJavaオブジェクトをJSONで、読みましょう。
利用XStream(http://x-stream.github.io/).もできるのでコントロールの特性を無視できじ注釈または明示的に指定のプロパティ名XStreamクラスです。またない実装する必要がclonableインターフェース。
のための Spring Framework ユーザー利用クラス org.springframework.util.SerializationUtils
:
@SuppressWarnings("unchecked")
public static <T extends Serializable> T clone(T object) {
return (T) SerializationUtils.deserialize(SerializationUtils.serialize(object));
}
Deepコピーできることとします各クラスにし、本人の同意を得て行います。の場合はクラス階層を実践できるのclonableスを実施するクローンの方法。ないディープコピーは不可能であるとので安心のオブジェクトが共有データの資源などデータベース接続).一般には深いコピーは不良の実践るドキュメンテーションシステム環境のため、回避されるべきである、適切な設計です。
import com.thoughtworks.xstream.XStream;
public class deepCopy {
private static XStream xstream = new XStream();
//serialize with Xstream them deserialize ...
public static Object deepCopy(Object obj){
return xstream.fromXML(xstream.toXML(obj));
}
}
複雑な物体が性能というわけではありませんが重要なのを使用していjsonライブラリのように、 gson にserializeのオブジェクトをjson文字、直列化復元のテキストを新しいオブジェクトです。
gsonれに基づく反射す作品のほとんどの場合を除き、その transient
分野コピーされません、オブジェクトの円形の参照が StackOverflowError
.
public static <T> T copy(T anObject, Class<T> classInfo) {
Gson gson = new GsonBuilder().create();
String text = gson.toJson(anObject);
T newObject = gson.fromJson(text, classInfo);
return newObject;
}
public static void main(String[] args) {
String originalObject = "hello";
String copiedObject = copy(originalObject, String.class);
}
1)
public static Object deepClone(Object object) {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(object);
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
return ois.readObject();
}
catch (Exception e) {
e.printStackTrace();
return null;
}
}
2)
// (1) create a MyPerson object named Al
MyAddress address = new MyAddress("Vishrantwadi ", "Pune", "India");
MyPerson al = new MyPerson("Al", "Arun", address);
// (2) make a deep clone of Al
MyPerson neighbor = (MyPerson)deepClone(al);
こちらでおMyPersonとMyAddressクラスが実装しなければならないserilazableェ
BeanUtils は本当に良い仕事を深くクローニング豆です。
BeanUtils.cloneBean(obj);