> Java > java지도 시간 > Java 직렬화 액세스로 구현된 객체 복제의 예에 대한 자세한 설명

Java 직렬화 액세스로 구현된 객체 복제의 예에 대한 자세한 설명

Y2J
풀어 주다: 2017-04-26 10:05:30
원래의
1266명이 탐색했습니다.

이 기사는 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 직렬화 액세스로 구현된 객체 복제의 예에 대한 자세한 설명

이 영역에는 동일한 값을 가리키는 두 개의 참조가 있습니다. 오른쪽 힙 영역에 있습니다.
대부분의 경우 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는 동일한 객체입니다! 그 이유는 복제를 사용하더라도 위의 내용은 얕은 복제일 뿐이며 그래픽으로 표현되기 때문입니다.

Java 직렬화 액세스로 구현된 객체 복제의 예에 대한 자세한 설명
위의 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 직렬화 액세스로 구현된 객체 복제의 예에 대한 자세한 설명

복제 작업이 완료되었습니다.

위 내용은 Java 직렬화 액세스로 구현된 객체 복제의 예에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿