이 기사는 Java 객체의 심층 복제를 달성하기 위한 직렬 액세스 방법에 대한 자세한 분석 및 소개입니다. 필요한 친구가 참고할 수 있습니다.
우리는 Java에서 프로토타입이 아닌 객체라는 것을 알고 있습니다. 참조, 다른 개체의 참조에 할당된 후 두 참조는 동일한 개체를 가리킵니다.
코드는 다음과 같습니다.
public class DeepCloneTest { private class CloneTest { private Long myLong = new Long(1); } public static void main(String args[]) { new DeepCloneTest().Test(); } public void Test() { CloneTest ct1 = new CloneTest(); CloneTest ct2 = ct1; // to see if ct1 and ct2 are one same reference. System.out.println("ct1: " + ct1); System.out.println("ct2: " + ct2); // if ct1 and ct2 point to one same object, then ct1.myLong == ct2.myLong. System.out.println("ct1.myLong: " + ct1.myLong); System.out.println("ct2.myLong: " + ct2.myLong); // we change ct2's myLong ct2.myLong = 2L; // to see whether ct1's myLong was changed. System.out.println("ct1.myLong: " + ct1.myLong); System.out.println("ct2.myLong: " + ct2.myLong); }}
출력:
ct1: DeepCloneTest$CloneTest@c17164
ct2: DeepCloneTest$CloneTest@c17164
ct1.myLong: 1
ct2.myLong: 1
ct1.myLong: 2
ct2.myLong: 2
아주 쉬우며, Java를 공부하는 분들은 다 아실 겁니다(모르시는 분들, Java를 공부하시는 분들?).
메모리에서는 객체의 참조가 스택에 저장되고 객체의 데이터가 힙에 저장되며 스택의 참조가 힙의 객체를 가리킵니다. 다음은 힙에 있는 동일한 객체를 가리키는 두 스택의 참조입니다. 따라서 ct2의 myLong이 변경되면 ct1의 myLong 값도 변경되는 것을 다이어그램으로 표현하면 쉽게 알 수 있습니다. :
이 영역에는 동일한 값을 가리키는 두 개의 참조가 있습니다. 오른쪽 힙 영역에 있습니다.
대부분의 경우 Java 언어의 이 기능을 사용하여 원하는 작업을 수행합니다. 예를 들어 객체 참조를 입력 매개변수로 메소드에 전달하고 메소드에서 해당 수정을 수행합니다. 참조가 가리키는 객체입니다. 그러나 때로는 기존 객체와 내용이 완전히 동일하지만 다른 객체를 참조하는 객체를 생성하려는 경우 에서 다음을 수행할 수 있습니다.
코드
public class DeepCloneTest{ // must implements Cloneable. private class CloneTest implements Cloneable{ private Object o = new Object(); public CloneTest clone() { CloneTest ct = null; try { ct = (CloneTest)super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return ct; } } public static void main(String args[]) { new DeepCloneTest().Test(); } public void Test() { CloneTest ct1 = new CloneTest(); CloneTest ct2 = ct1.clone(); // to see if ct1 and ct2 are one same reference. System.out.println("ct1: " + ct1); System.out.println("ct2: " + ct2); // whether ct1.o == ct2.o ? yes System.out.println("ct1.o " + ct1.o); System.out.println("ct1.o " + ct1.o); }}
출력:
ct1: DeepCloneTest$CloneTest@c17164
ct2: DeepCloneTest$CloneTest@1fb8ee3
ct1.o java.lang.Object@61de33
ct1.o java .lang.Object@61de33
출력에서 볼 수 있듯이: ct1과 ct2는 실제로 두 개의 다른 참조이므로 ct1.o와 ct2.o도 서로 다른 두 개체라는 것을 당연하게 여깁니다. 하지만 출력을 보면 그렇지 않다는 것을 알 수 있습니다! ct1.o와 ct2.o는 동일한 객체입니다! 그 이유는 복제를 사용하더라도 위의 내용은 얕은 복제일 뿐이며 그래픽으로 표현되기 때문입니다.
위의 o를 보시겠습니까? 실제로는 두 개체가 공유합니다. 이는 원래 양이 들어 있는 양 우리 1이 있었고, 그 다음에는 양 우리 2를 만들었습니다. 양 우리 1에서 양을 꺼내지 않고 우리 2에도 양을 넣었다고 생각했습니다. 양 두 마리인데 실제로는요? 모두가 그것을 알고 있습니다.
얕은 복제의 결과는 다음과 같습니다. 두 개체가 독립적인 o를 가지도록 하려면 o를 다시 복제해야 합니다. 별거 아니라고 생각하시는 분들도 계시겠지만, 혹시 o가 하나 이상 있고, o와 비슷한 게 너무 많으면 하나씩 복제해 보시는 건 어떨까요? 분명히 그것은 비현실적입니다.
한 가지 해결책은 다음과 같습니다. 먼저 객체를 직렬화하여 스트림에 저장한 다음 스트림에서 객체를 읽어서 읽을 수 있도록 합니다. 이전 개체의 값은 완전한 복사본과 마찬가지로 완전히 동일합니다.
코드는 다음과 같습니다.
import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; public class DeepCloneTest { // must implements Cloneable. private class CloneTest implements Serializable{ private static final long serialVersionUID = 1L; private Object o = new Object(); public CloneTest deepClone() { CloneTest ct = null; try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(this); ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); ObjectInputStream ois= new ObjectInputStream(bais); ct = (CloneTest)ois.readObject(); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } return ct; } } public static void main(String args[]) { new DeepCloneTest().Test(); } public void Test() { CloneTest ct1 = new CloneTest(); CloneTest ct2 = ct1.deepClone(); // to see if ct1 and ct2 are one same reference. System.out.println("ct1: " + ct1); System.out.println("ct2: " + ct2); // whether ct1.o == ct2.o ? no System.out.println("ct1.o " + ct1.o); System.out.println("ct1.o " + ct1.o); } }
이때 메모리에 있는 데이터는 다음과 같습니다.
복제 작업이 완료되었습니다.
위 내용은 Java 직렬화 액세스로 구현된 객체 복제의 예에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!