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




인스턴스 깊은 (18)

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

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 ?


Answers

class DB {
  private String dummy;

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

다음과 같이하면됩니다.

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

http://x-stream.github.io/ 에서 XStream으로 자동 복사가 가능합니다 :

XStream은 객체를 XML로 직렬화하고 다시 직렬화하는 간단한 라이브러리입니다.

프로젝트에 추가하십시오 (maven을 사용하는 경우).

<dependency>
    <groupId>com.thoughtworks.xstream</groupId>
    <artifactId>xstream</artifactId>
    <version>1.3.1</version>                
</dependency>

그때

DummyBean dum = new DummyBean();
dum.setDummy("foo");
DummyBean dumCopy = (DummyBean) XSTREAM.fromXML(XSTREAM.toXML(dum));

이것으로 복제 인터페이스를 구현할 필요없이 사본을 얻을 수 있습니다.


Reflection API 사용에 대한 답변이없는 이유는 무엇입니까?

private static Object cloneObject(Object obj){
        try{
            Object clone = obj.getClass().newInstance();
            for (Field field : obj.getClass().getDeclaredFields()) {
                field.setAccessible(true);
                field.set(clone, field.get(obj));
            }
            return clone;
        }catch(Exception e){
            return null;
        }
    }

정말 간단합니다.

편집 : 재귀를 통해 자식 개체 포함

private static Object cloneObject(Object obj){
        try{
            Object clone = obj.getClass().newInstance();
            for (Field field : obj.getClass().getDeclaredFields()) {
                field.setAccessible(true);
                if(field.get(obj) == null || Modifier.isFinal(field.getModifiers())){
                    continue;
                }
                if(field.getType().isPrimitive() || field.getType().equals(String.class)
                        || field.getType().getSuperclass().equals(Number.class)
                        || field.getType().equals(Boolean.class)){
                    field.set(clone, field.get(obj));
                }else{
                    Object childObj = field.get(obj);
                    if(childObj == obj){
                        field.set(clone, clone);
                    }else{
                        field.set(clone, cloneObject(field.get(obj)));
                    }
                }
            }
            return clone;
        }catch(Exception e){
            return null;
        }
    }



클래스에 CloneableCloneable 코드 추가

public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

clonedObject = (YourClass) yourClassObject.clone();


public class MyClass implements Cloneable {

private boolean myField= false;
// and other fields or objects

public MyClass (){}

@Override
public MyClass clone() throws CloneNotSupportedException {
   try
   {
       MyClass clonedMyClass = (MyClass)super.clone();
       // if you have custom object, then you need create a new one in here
       return clonedMyClass ;
   } catch (CloneNotSupportedException e) {
       e.printStackTrace();
       return new MyClass();
   }

  }
}

코드에서

MyClass myClass = new MyClass();
// do some work with this object
MyClass clonedMyClass = myClass.clone();

이것도 작동합니다. 모델 가정

class UserAccount{
   public int id;
   public String name;
}

먼저 앱> gradle & sync에 compile 'com.google.code.gson:gson:2.8.1' 을 추가하십시오. 그때

Gson gson = new Gson();
updateUser = gson.fromJson(gson.toJson(mUser),UserAccount.class);

액세스 한정자 다음에 transient 키워드를 사용하여 필드를 사용하여 제외 할 수 있습니다.

참고 : 이것은 나쁜 습관입니다. 또한 Cloneable 또는 JavaSerialization 을 사용하지 않는 것이 좋습니다. 느리고 깨졌습니다. 최고의 성능을위한 복사 생성자를 작성하십시오.

좋아하는 것

class UserAccount{
        public int id;
        public String name;
        //empty constructor
        public UserAccount(){}
        //parameterize constructor
        public UserAccount(int id, String name) {
            this.id = id;
            this.name = name;
        }

        //copy constructor
        public UserAccount(UserAccount in){
            this(in.id,in.name);
        }
    }

90000 반복 테스트 통계 :
Line UserAccount clone = gson.fromJson(gson.toJson(aO), UserAccount.class); 808ms 걸린다.

Line UserAccount clone = new UserAccount(aO); 1ms 미만 걸린다.

결론 : 사장님이 미쳐서 스피드를 좋아하시면 gson을 사용하십시오. 품질을 선호하는 경우 두 번째 복사본 생성자를 사용하십시오.

Android Studio에서 복사 생성자 코드 생성기 플러그인 을 사용할 수도 있습니다.


예, 객체에 대한 참조 만하고 있습니다. Cloneable 을 구현하는 경우 개체를 복제 할 수 있습니다.

객체 복사에 관한이 wiki 기사를 확인하십시오.

객체 복사


복사하려는 객체를 전달하고 원하는 객체를 가져옵니다.

private Object copyObject(Object objSource) {
        try {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bos);
            oos.writeObject(objSource);
            oos.flush();
            oos.close();
            bos.close();
            byte[] byteData = bos.toByteArray();
            ByteArrayInputStream bais = new ByteArrayInputStream(byteData);
            try {
                objDest = new ObjectInputStream(bais).readObject();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return objDest;

    }

이제 objDest 를 원하는 객체로 파싱합니다.

해피 코딩!


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

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();

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


패키지에서 import org.apache.commons.lang.SerializationUtils; 방법이 있습니다.

SerializationUtils.clone(Object);

예:

this.myObjectCloned = SerializationUtils.clone(this.object);

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

dumtwo = dum.copy();

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



명시 적으로 복사하는 것 외에도 다른 방법은 객체를 변경 불가능하게 만드는 것입니다 ( set 또는 다른 변형 메소드를 사용하지 마십시오). 이런 식으로 질문이 결코 발생하지 않습니다. 불변성은 큰 물체의 경우 더 어려워집니다.하지만 그 다른면은 일관된 작은 물체와 합성물로 분리되는 방향으로 당신을 밀어 넣는 것입니다.


thing[:] 사용 thing[:]

>>> a = [1,2]
>>> b = a[:]
>>> a += [3]
>>> a
[1, 2, 3]
>>> b
[1, 2]
>>> 




java object copy clone