아래 코드를 고려하십시오.
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변화 dum에 영향을주지 않고 dumtwo. 그러나 위의 코드는 그렇게하지 않습니다. 에서 무언가를 변경 dum하면 동일한 변화가 발생 dumtwo합니다.
내가 말할 때 dumtwo = dumJava는 참조 만 복사 한다고 생각 합니다 . 따라서 새로운 사본을 만들어 dum할당 할 수있는 방법이 dumtwo있습니까?
답변
복사 생성자를 만듭니다.
class DummyBean {
private String dummy;
public DummyBean(DummyBean another) {
this.dummy = another.dummy; // you can access
}
}
모든 객체에는 객체를 복사하는 데 사용할 수있는 복제 방법도 있지만 사용하지는 마십시오. 클래스를 생성하고 부적절한 클론 메소드를 수행하는 것은 너무 쉬운 방법입니다. 그렇게하려면 적어도 Joshua Bloch가 Effective Java 에서 그것에 대해 말한 내용을 읽으십시오 .
답변
기본 : Java에서 객체 복사.
우리는 객체 – 가정하자 obj1, 그 두 개체가 포함되어 containedObj1 및 containedObj2을 .

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

딥 카피 : 딥 카피 는 객체를 참조하는 객체와 함께 객체를 복사
할 때 발생합니다 . 아래 이미지는 깊은 복사가 수행 된 후의 모습 입니다. 있다뿐만 아니라 복사 ,하지만 그 안에 포함 된 개체가 아니라 복사 한. 딥 카피를 만드는 데 사용할 수 있습니다 . 불행히도,이 접근 방식에는 몇 가지 문제가 있습니다 ( 자세한 예 ).obj1obj1Java Object Serialization

가능한 문제 :
clone 올바르게 구현하기가 까다 롭습니다. 방어 복사 , 복사 생성자 (@egaga 회신) 또는 정적 팩토리 메소드
를 사용하는 것이 좋습니다 .
- 객체가 있고 공개
clone()메소드가 있지만 컴파일 타임에 객체의 유형을 모르는 경우 문제가 있습니다. Java에는라는 인터페이스가Cloneable있습니다. 실제로 객체를 만들려면이 인터페이스를 구현해야합니다Cloneable.Object.cloneis protected 이므로 액세스하려면 공개 메소드로 덮어 써야 합니다. - 우리가하려고 할 때 또 다른 문제가 발생 깊은 복사 (A)의 복잡한 객체를 .
clone()모든 멤버 객체 변수 의 메소드도 딥 카피를 수행 한다고 가정하면 너무 가정이 위험합니다. 모든 클래스에서 코드를 제어해야합니다.
예를 들어 org.apache.commons.lang.SerializationUtils 에는 serialization ( Source )을 사용하는 딥 클론 방법이 있습니다 . Bean을 복제해야하는 경우 org.apache.commons.beanutils ( Source ) 에 몇 가지 유틸리티 메소드가 있습니다.
cloneBeanBean 클래스 자체가 Cloneable을 구현하지 않더라도 사용 가능한 특성 getter 및 setter를 기반으로 Bean을 복제합니다.copyProperties등록 정보 이름이 동일한 모든 경우에 대해 원점 Bean에서 대상 Bean으로 등록 정보 값을 복사합니다.
답변
패키지 import org.apache.commons.lang.SerializationUtils;에는 다음과 같은 방법이 있습니다.
SerializationUtils.clone(Object);
예:
this.myObjectCloned = SerializationUtils.clone(this.object);
답변
다음과 같이 따르십시오.
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
답변
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;
}
}
답변
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;
}
}
