실례 분석 자바 대상 중 얕은 복제와 깊은 복제

10186 단어
인용문:
Object 기본 클래스에서 clone이라는 방법이 있는데 초기 대상의 복제를 생성한다. 복제 대상은 원래 대상의 복사이다. 인용 유형의 존재로 인해 깊은 복제와 얕은 복제의 구분이 있다. 만약에 복제 대상에 인용 유형의 속성이 존재한다면 깊은 복제는 이 속성을 완전히 복사하지만 얕은 복제는 이 속성의 인용만 복사한다.우선 범하기 쉬운 몇 가지 사소한 문제들을 보도록 하겠습니다.
Clone 방법은 Object 클래스이고 Cloneable 인터페이스가 아니다. Cloneable는 하나의 표시 인터페이스일 뿐이다. 표시 인터페이스는 사용자가 이 인터페이스를 실현하는 클래스로 특정한 인터페이스 표시 기능을 가진다. 흔히 볼 수 있는 표시 인터페이스는 세 가지가 있는데 그것이 바로 Serializable, Cloneable, RandomAccess이다. Cloneable 인터페이스를 실현하지 못하면 Clone 방법을 호출하면 CloneNotSupportedException 이상이 발생한다.
Object 클래스의clone 방법은 보호된 것입니다. 이것은 하위 클래스에서 이 방법을 다시 쓰지 않으면 하위 클래스 밖에서 접근할 수 없다는 것을 보여 줍니다. 이 보호된 권한은 Object가 있는 가방과 하위 클래스에서만 접근할 수 있기 때문입니다. 또한 하위 클래스에서 부모 방법을 다시 쓰는 방법 권한 수식자는 커질 수 있지만 작아질 수 없다는 것을 검증했습니다.

protected native Object clone() throws CloneNotSupportedException;

clone 방법을 다시 쓰는 것은 내부에서 부모 클래스의 clone 방법을 호출한 것일 뿐입니다. 사실은 접근 권한을 확대하기 위해서입니다. 물론 보호된 방법을public로 바꿀 수 있습니다. 나중에 계승하면 다시 쓸 필요가 없습니다.물론 얕은 복제의 클론 함수일 뿐, 깊은 복제는 수정이 필요하다.

@Override  
protected Object clone() throws CloneNotSupportedException {    
 return super.clone();
}

속성은 String의 경우 String도 하나의 클래스입니다. 그러면 String은 유형을 인용합니까?String의 표현은 기본적인 유형과 비슷하다. 결국 String은 바꿀 수 없기 때문이다. 복제 후 두 인용은 같은 String을 가리키지만 그 중 하나를 수정하면 String의 값이 아니라 새로 문자열을 생성하여 수정된 인용이 새로운 문자열을 가리키게 한다.겉모습은 기본 타입처럼 보인다.
간단한 클론:
천크론은 인용 유형의 속성을 완전히 복제할 수 없는 것이다. 클래스 User에 성적 속성이 포함된 마크, 마크는 Chinese와 math 등으로 구성되어 있는데 천크론 실패의 예이다.

class Mark{
  private int chinese;
  private int math;
  public Mark(int chinese, int math) {
    this.chinese = chinese;
    this.math = math;
  }
 
  public void setChinese(int chinese) {
    this.chinese = chinese;
  }
 
  public void setMath(int math) {
    this.math = math;
  }
 
  @Override
  public String toString() {
    return "Mark{" +
        "chinese=" + chinese +
        ", math=" + math +
        '}';
  }
}
public class User implements Cloneable{
  private String name;
  private int age;
  private Mark mark;
 
  public User(String name, int age,Mark mark) {
    this.name = name;
    this.age = age;
    this.mark = mark;
  }
 
  @Override
  public String toString() {
    return "User{" +
        "name='" + name + '\'' +
        ", age=" + age +
        ", mark=" + mark +
        '}';
  }
 
  @Override
  protected Object clone() throws CloneNotSupportedException {
    return super.clone();
  }
 
  public static void main(String[] args) throws CloneNotSupportedException {
    Mark mark = new Mark(100,99);
    User user = new User("user",22,mark);
    User userClone = (User) user.clone();
    System.out.println(" user:"+user);
    System.out.println(" user:"+userClone);
    // mark 
    user.mark.setMath(60);
    System.out.println(" user:"+user);
    System.out.println(" user:"+userClone);
  }
}

출력 결과는 다음과 같습니다.
원 user: User {name='user', age=22,mark=Mark=Mark {chinese=100, math=99}} 복제된user: User {name='user', age=22,mark=Mark={chinese=100, math=100, math=99} 수정된 원 user: User {name='user', age=22,mark=Mark={chinese=100, math=60} 수정된 복제된user: User {name='user', Markchines=60}
user의mark가 변경된 것을 똑똑히 보고 복제된user도 수정했습니다.영향을 받지 않으려면 깊이 복제해야 한다.
딥 클론:
방식 1:clone 함수의 플러그인 호출
인용 형식이 완전히 복제될 수 없으면 인용 형식도 Cloneable 인터페이스에서 clone 방법을 다시 쓰기를 실현하고 User 클래스에서 clone 방법은 속성의 복제 방법, 즉 방법의 끼워넣기 호출을 호출합니다

class Mark implements Cloneable{
  private int chinese;
  private int math;
  public Mark(int chinese, int math) {
    this.chinese = chinese;
    this.math = math;
  }
  public void setChinese(int chinese) {
    this.chinese = chinese;
  }
  public void setMath(int math) {
    this.math = math;
  }
  @Override
  protected Object clone() throws CloneNotSupportedException {
    return super.clone();
  }
  @Override
  public String toString() {
    return "Mark{" +
        "chinese=" + chinese +
        ", math=" + math +
        '}';
  }
}
public class User implements Cloneable{
  private String name;
  private int age;
  private Mark mark;
 
  public User(String name, int age,Mark mark) {
    this.name = name;
    this.age = age;
    this.mark = mark;
  }
 
  @Override
  public String toString() {
    return "User{" +
        "name='" + name + '\'' +
        ", age=" + age +
        ", mark=" + mark +
        '}';
  }
 
  @Override
  protected Object clone() throws CloneNotSupportedException {
    User user = (User) super.clone();
    user.mark = (Mark) this.mark.clone();
    return user;
  }
 
  public static void main(String[] args) throws CloneNotSupportedException {
    Mark mark = new Mark(100,99);
    User user = new User("user",22,mark);
    User userClone = (User) user.clone();
    System.out.println(" user:"+user);
    System.out.println(" user:"+userClone);
    // mark 
    user.mark.setMath(60);
    System.out.println(" user:"+user);
    System.out.println(" user:"+userClone);
  }
}

출력 결과는 다음과 같습니다.
원래 user: User {name='user', age=22,mark=Mark=Mark {chinese=100, math=99} 복제된user: User {name='user', age=22,mark=Mark={chinese=100, math=99} 수정된 원user: User {name='user', age=22,mark=Mark={chinese=100, math=60} 수정된 복제된user: User{name='user', Markage=99}
방식 2: 서열화
이전 방법은 우리의 수요를 충족시킬 수 있지만 클래스 간의 관계가 많거나 어떤 속성이 수조라면 수조는 Cloneable 인터페이스를 실현할 수 없다. (우리는 clone 방법에서 수조를 수동으로 복제할 수 있다) 그러나 매번 손으로 clone 방법을 써야 하기 때문에 매우 번거롭다. 서열화 방식은 클래스마다 하나의 Serializable 인터페이스를 실현하고 표시 인터페이스이기도 하다.마지막으로 동일 서열화와 반서열화 작업은 복제의 목적(수조의 복제 포함)에 도달했다.서열화와 반서열화의 지식은 다음 편을 참조하시오

import java.io.*;
class Mark implements Serializable {
  private int chinese;
  private int math;
  public Mark(int chinese, int math) {
    this.chinese = chinese;
    this.math = math;
}
  public void setChinese(int chinese) {
    this.chinese = chinese;
  }
  public void setMath(int math) {
    this.math = math;
  }
  @Override
  public String toString() {
    return "Mark{" +
        "chinese=" + chinese +
        ", math=" + math +
        '}';
  }
}
public class User implements Serializable{
  private String name;
  private int age;
  private Mark mark;
 
  public User(String name, int age,Mark mark) {
    this.name = name;
    this.age = age;
    this.mark = mark;
  }
 
  @Override
  public String toString() {
    return "User{" +
        "name='" + name + '\'' +
        ", age=" + age +
        ", mark=" + mark +
        '}';
  }
  public static void main(String[] args) throws IOException, ClassNotFoundException {
    Mark mark = new Mark(100,99);
    User user = new User("user",22,mark);
 
    ByteArrayOutputStream bo = new ByteArrayOutputStream();
    ObjectOutputStream oo = new ObjectOutputStream(bo);
    oo.writeObject(user);// 
    ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
    ObjectInputStream oi = new ObjectInputStream(bi);
    User userClone = (User) oi.readObject();// 
 
    System.out.println(" user:"+user);
    System.out.println(" user:"+userClone);
    user.mark.setMath(59);
    System.out.println(" user:"+user);
    System.out.println(" user:"+userClone);
  }
}

결과 출력:
원래 user: User {name='user', age=22,mark=Mark=Mark {chinese=100, math=99} 복제된user: User {name='user', age=22,mark=Mark={chinese=100, math=99} 수정된 원user: User {name='user', age=22,mark=Mark={chinese=100, math=60} 수정된 복제된user: User{name='user', Markage=99}
배열 속성이 있는 클론

import java.io.*;
import java.util.Arrays;
 
public class User implements Serializable{
  private String name;
  private int age;
  private int[] arr;
 
  public User(String name, int age, int[] arr) {
    this.name = name;
    this.age = age;
    this.arr = arr;
  }
  @Override
  public String toString() {
    return "User{" +
        "name='" + name + '\'' +
        ", age=" + age +
        ", arr=" + Arrays.toString(arr) +
        '}';
  }
  public static void main(String[] args) throws IOException, ClassNotFoundException {
    int[] arr = {1,2,3,4,5,6};
    User user = new User("user",22,arr);
 
    ByteArrayOutputStream bo = new ByteArrayOutputStream();
    ObjectOutputStream oo = new ObjectOutputStream(bo);
    oo.writeObject(user);// 
    ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
    ObjectInputStream oi = new ObjectInputStream(bi);
    User userClone = (User) oi.readObject();// 
 
    System.out.println(" user:"+user);
    System.out.println(" user:"+userClone);
    user.arr[1] = 9;
    System.out.println(" user:"+user);
    System.out.println(" user:"+userClone);
  }
}

좋은 웹페이지 즐겨찾기