문제
자바에서 조금 구현하기 어려운 깊은 개체 복사 기능이다.What 하기 위해 수행하는 단계를 지키는 원래 개체 복제나 공유하지 않나요?
해결책
안전한 방법으로 직렬화를 직렬화.이것은 모든 것이 새로운 참조.
여기에 문서 에 대해 수행하는 방법이 효율적으로 합니다.
주의 사항:그것이 가능한 클래스를 재정의를 직렬화하는 등 새 인스턴스 지 만들어,예를 들어,에 대한 singleton.또한 이 코스의 작동하지 않는 경우에 당신의 클래스가 없는 직렬화.
다른 팁
몇 사람을 사용하여 언급 또는 재정의 Object.clone()
.그것을 하지 않는다. Object.clone()
는 몇 가지 중요한 문제이며,그 사용은 권장하지 않습니다.항목을 참조하십시오 11"효과적인 자바"여호수아의 블로흐에 대한 완전한 대답합니다.내가 믿고 안전하게 사용할 수 있는 Object.clone()
에는 기본 형식 어레이,하지만 떨어져야 하는 것을 현명에 대해 제대로 사용하고 재정의 클론입니다.
계획에 의존하는 직렬화 XML(또는 그렇지 않으면)의 의견을 더욱 쉽게 확인.
이 없기 쉽답니다 여기에.하려면 깊은 복사한 객체가 있을 것이를 통과 개체 그래프 및 각각 복사 자식 개체를 통해 명시적으로 물체의 복사본을 생성자 또는 정적 공장하는 방법에 차례 깊이에 복사합니다.Immutables(예: String
s)이 필요하지 않습을 복사할 수 있습니다.옆으로,당신은 당신의 면역성이 이유입니다.
할 수 있게 깊은 사본으로 직렬화를 만들지 않고 파일이 있습니다.
귀하의 개체를 원하는 깊은 사본이 필요하 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;
}
}
편집:참고 사용할 경우 복사본을 생성자를 알아야 합타 개체의 유형은 당신이 검사를 사용하지 않습니다.위의 접근을 쉽게 복사할 수 없습 혼합 목록(할 수 있습니다 그것을 일부 반사 코드).
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 은 정말 유용 등의 인스턴스가 있습니다.여기에 간단한 코드를 복제 do
private static final XStream XSTREAM = new XStream();
...
Object newObject = XSTREAM.fromXML(XSTREAM.toXML(obj));
하나는 매우 쉽고 간단하게 접근 방식을 사용하여 잭슨 JSON 직렬화하여 복잡한 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));
}
깊은 복사를 수행 할 수 있습과 각 클래스의 동의를 얻어야 합니다.면 통제가 있는 클래스 계층 다음을 구현할 수 있습 clonable 인터페이스 구현은 복제 방법입니다.그렇지 않으면을 깊이에 복사하는 것은 불가능 하기 때문에 안전하게 개체될 수도 있습을 공유 비 데이터 리소스(예:데이터베이스에 연결).일반적으로 그러나 깊은 복사하는 것은 나쁜 것으로 간주에서 연습 Java 환경 및 피해야를 통해 적절한 디자인 방법.
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 라이브러리아 코드 를 직렬화하는 개체를 json 텍스트,그 직렬화의 텍스트를 얻을 새로운 개체입니다.
코드에 따라 반사는 대부분의 경우 작동하는 것을 제외하고, 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);