clone 자바 Java로 객체를 어떻게 복사합니까?




10 Answers

기본 : 자바에서 객체 복사.

두 객체 obj1containedObj2 를 포함하는 객체 obj1 가정 해보자.

얕은 복사 :
얕은 복사는 동일한 클래스의 새 instance 를 만들고 모든 필드를 새 인스턴스에 복사 한 다음 반환합니다. Object 클래스clone 메서드를 제공하고 얕은 복사를 지원합니다.

딥 복사 :
전체 복사본 은 개체가 참조 할 개체와 함께 복사 될 때 발생합니다. 아래 이미지는 딥 복사가 수행 된 후 obj1 을 보여줍니다. obj1 이 복사되었을 뿐만 아니라 그 안에 포함 된 객체도 복사됩니다. Java Object Serialization 을 사용하여 전체 복사본을 만들 수 있습니다. 불행히도이 접근법에는 몇 가지 문제점이 있습니다 ( 자세한 예제 ).

가능한 문제점 :
clone 은 올바르게 구현하기 까다 롭습니다.
방어 복사 , 복사 생성자 (@egaga 응답) 또는 정적 팩토리 메소드 를 사용하는 것이 좋습니다.

  1. public clone() 메서드를 가지고있는 객체가 있지만 컴파일 타임에 객체의 유형을 알지 못하면 문제가 발생합니다. Java에는 Cloneable 이라는 Cloneable 있습니다. 실제로 객체를 Cloneable 으로 만들려면이 인터페이스를 구현해야합니다. Object.clone보호 되어 있으므로 액세스하기 위해서는 public 메서드로 재정의 해야합니다.
  2. 또 다른 문제는 복잡한 객체완전한 복사 를 시도 할 때 발생 합니다 . 모든 멤버 객체 변수의 clone() 메소드가 딥 복사를한다고 가정합니다. 이것은 너무 위험합니다. 모든 클래스의 코드를 제어해야합니다.

예를 들어, org.apache.commons.lang.SerializationUtils 는 직렬화 ( Source )를 사용하여 딥 클론을위한 메소드를 갖습니다. Bean을 복제해야한다면 org.apache.commons.beanutils ( Source )에 몇 가지 유틸리티 메소드가있다.

  • cloneBean 은 빈 클래스 자체가 Cloneable을 구현하지 않더라도 사용 가능한 속성 getter 및 setter를 기반으로 빈을 복제합니다.
  • copyProperties 는 속성 이름이 같은 모든 경우에 대해 원두 bean에서 대상 bean으로 속성 값을 복사합니다.
자바 복사

아래 코드를 살펴보십시오.

DummyBean dum = new DummyBean();
dum.setDummy("foo");
System.out.println(dum.getDummy()); // prints 'foo'

DummyBean dumtwo = dum;
System.out.println(dumtwo.getDummy()); // prints 'foo'

dum.setDummy("bar");
System.out.println(dumtwo.getDummy()); // prints 'bar' but it should print 'foo'

그래서 나는 dum 을 복사해서 dumtwo 영향을주지 않으면 서 dumdumtwo dumtwo . 그러나 위의 코드는 그렇게하지 않습니다. 내가 dumtwo 뭔가를 바꿀 dumtwo 똑같은 변화가 일어나고 있습니다.

dumtwo = dum 이라고 dumtwo = dum Java는 참조 만 복사합니다. 그럼, dum 의 새로운 복사본을 만들고 그것을 dumtwo 할당하는 방법이 dumtwo ?




다음과 같이하면됩니다.

public class Deletable implements Cloneable{

    private String str;
    public Deletable(){
    }
    public void setStr(String str){
        this.str = str;
    }
    public void display(){
        System.out.println("The String is "+str);
    }
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

어디서나 다른 객체를 가져오고 싶다면 간단하게 복제를 수행하십시오. 예 :

Deletable del = new Deletable();
Deletable delTemp = (Deletable ) del.clone(); // this line will return you an independent
                                 // object, the changes made to this object will
                                 // not be reflected to other object



Google의 JSON 라이브러리를 사용하여 직렬화 한 다음 직렬화 된 객체의 새 인스턴스를 만듭니다. 몇 가지 제한 사항과 함께 깊은 복사를 수행합니다.

  • 재귀 적 참조는있을 수 없다.

  • 이종 유형의 배열을 복사하지 않습니다.

  • 배열과 목록을 입력해야합니다. 그렇지 않으면 인스턴스를 생성 할 클래스를 찾지 못합니다.

  • 자신을 선언 한 클래스에 문자열을 캡슐화해야 할 수도 있습니다.

또한이 클래스를 사용하여 런타임에 사용자 기본 설정, 윈도우 및 기타 등등을 다시로드합니다. 사용하기 쉽고 효과적입니다.

import com.google.gson.*;

public class SerialUtils {

//___________________________________________________________________________________

public static String serializeObject(Object o) {
    Gson gson = new Gson();
    String serializedObject = gson.toJson(o);
    return serializedObject;
}
//___________________________________________________________________________________

public static Object unserializeObject(String s, Object o){
    Gson gson = new Gson();
    Object object = gson.fromJson(s, o.getClass());
    return object;
}
       //___________________________________________________________________________________
public static Object cloneObject(Object o){
    String s = serializeObject(o);
    Object object = unserializeObject(s,o);
    return object;
}
}









그렇게하기 위해서는 객체를 어떤 식 으로든 복제해야합니다. Java에는 복제 메커니즘이 있지만, 필요하지 않은 경우에는 사용하지 마십시오. 복사 작업을 수행하는 복사 방법을 만들어 다음 작업을 수행하십시오.

dumtwo = dum.copy();

Here 은 복사본을 완성하기위한 다양한 기술에 대한 조언입니다.







class DB {
  private String dummy;

  public DB(DB one) {
    this.dummy = one.dummy; 
  }
}



Cloneable 을 구현하고 clone() 메서드를 사용할 수 있습니다. 그러나 복제 방법을 사용하는 경우 표준에 따라 항상 Objectpublic Object clone() 메서드를 재정의해야합니다.




주석을 소스 파일에 추가 할 수있는 경우이 주석 처리기 또는 코드 생성기를 사용할 수 있습니다.

import net.zerobuilder.BeanBuilder

@BeanBuilder
public class DummyBean { 
  // bean stuff
}

DummyBeanBuilders 클래스가 생성되어, 수동으로 수행하는 것과 같은 방법으로 얕은 복사본을 만드는 정적 메서드 인 dummyBeanUpdater 가 있습니다.

DummyBean bean = new DummyBean();
// Call some setters ...
// Now make a copy
DummyBean copy = DummyBeanBuilders.dummyBeanUpdater(bean).done();



Related