문제

자바에서 조금 구현하기 어려운 깊은 개체 복사 기능이다.What 하기 위해 수행하는 단계를 지키는 원래 개체 복제나 공유하지 않나요?

도움이 되었습니까?

해결책

안전한 방법으로 직렬화를 직렬화.이것은 모든 것이 새로운 참조.

여기에 문서 에 대해 수행하는 방법이 효율적으로 합니다.

주의 사항:그것이 가능한 클래스를 재정의를 직렬화하는 등 새 인스턴스 만들어,예를 들어,에 대한 singleton.또한 이 코스의 작동하지 않는 경우에 당신의 클래스가 없는 직렬화.

다른 팁

몇 사람을 사용하여 언급 또는 재정의 Object.clone().그것을 하지 않는다. Object.clone() 는 몇 가지 중요한 문제이며,그 사용은 권장하지 않습니다.항목을 참조하십시오 11"효과적인 자바"여호수아의 블로흐에 대한 완전한 대답합니다.내가 믿고 안전하게 사용할 수 있는 Object.clone() 에는 기본 형식 어레이,하지만 떨어져야 하는 것을 현명에 대해 제대로 사용하고 재정의 클론입니다.

계획에 의존하는 직렬화 XML(또는 그렇지 않으면)의 의견을 더욱 쉽게 확인.

이 없기 쉽답니다 여기에.하려면 깊은 복사한 객체가 있을 것이를 통과 개체 그래프 및 각각 복사 자식 개체를 통해 명시적으로 물체의 복사본을 생성자 또는 정적 공장하는 방법에 차례 깊이에 복사합니다.Immutables(예: Strings)이 필요하지 않습을 복사할 수 있습니다.옆으로,당신은 당신의 면역성이 이유입니다.

할 수 있게 깊은 사본으로 직렬화를 만들지 않고 파일이 있습니다.

귀하의 개체를 원하는 깊은 사본이 필요하 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 으로 읽습니다.

http://wiki.fasterxml.com/JacksonInFiveMinutes

사용 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);
}

내가 사용하는 도저 에 대한 복제 java 체 및 그것의 좋은 것, Kryo 라이브러리는 또 다른 좋은 대안입니다.

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);
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top