자바 의 깊 은 복사 와 얕 은 복사 소개
10481 단어 딥 카피
2.얕 은 복사 1.얕 은 복사 가 무엇 입 니까? 얕 은 복사 본 은 위치 에 따라 복사 대상 으로 새로운 대상 을 만 들 것 입 니 다.이 대상 은 원시 대상 속성 값 의 정확 한 복사 본 을 가지 고 있 습 니 다.속성 이 기본 유형 이 라면 기본 유형의 값 을 복사 합 니 다.속성 이 메모리 주소(참조 형식)라면 메모리 주 소 를 복사 합 니 다.따라서 한 대상 이 이 주 소 를 바 꾸 면 다른 대상 에 게 영향 을 줄 수 있 습 니 다.
그림 에서 SourceObject 는 int 형식의 속성 인'field 1'과 인용 유형 속성 인'refObj'(Contained Object 형식의 대상 참조)가 있 습 니 다.SourceObject 를 얕 게 복사 할 때 CopiedObject 를 만 들 었 습 니 다."field 1"복사 값 을 포함 하 는 속성 인"field 2"와 refObj 자 체 를 가리 키 는 참조 가 있 습 니 다."field 1"은 기본 형식 이기 때문에 값 을"field 2"에 복사 할 뿐"refObj"는 참조 형식 이기 때문에 CopiedObject 는"refObj"와 같은 주 소 를 가리 키 고 있 습 니 다.따라서 SourceObject 의'refObj'에 대한 어떠한 변화 도 CopiedObject 에 영향 을 줄 수 있다.
2.얕 은 복사 어떻게 실현
다음은 얕 은 복사 본 을 실현 하 는 예 이다
public class Subject {
private String name;
public Subject(String s) {
name = s;
}
public String getName() {
return name;
}
public void setName(String s) {
name = s;
}
}
public class Student implements Cloneable {
//
private Subject subj;
private String name;
public Student(String s, String sub) {
name = s;
subj = new Subject(sub);
}
public Subject getSubj() {
return subj;
}
public String getName() {
return name;
}
public void setName(String s) {
name = s;
}
/**
* clone()
* @return
*/
public Object clone() {
//
try {
// clone()
return super.clone();
} catch (CloneNotSupportedException e) {
return null;
}
}
}
public class CopyTest {
public static void main(String[] args) {
//
Student stud = new Student("John", "Algebra");
System.out.println("Original Object: " + stud.getName() + " - " + stud.getSubj().getName());
//
Student clonedStud = (Student) stud.clone();
System.out.println("Cloned Object: " + clonedStud.getName() + " - " + clonedStud.getSubj().getName());
// :
System.out.println("Is Original Object the same with Cloned Object: " + (stud == clonedStud));
// name
System.out.println("Is Original Object's field name the same with Cloned Object: " +
(stud.getName() == clonedStud.getName()));
// subj
System.out.println("Is Original Object's field subj the same with Cloned Object: " +
(stud.getSubj() == clonedStud.getSubj()));
stud.setName("Dan");
stud.getSubj().setName("Physics");
System.out.println("Original Object after it is updated: " + stud.getName() + " - " +
stud.getSubj().getName());
System.out.println("Cloned Object after updating original object: " + clonedStud.getName() +
" - " + clonedStud.getSubj().getName());
}
}
출력 결 과 는 다음 과 같 습 니 다. Original Object: John - Algebra Cloned Object: John - Algebra Is Original Object the same with Cloned Object: false Is Original Object's field name the same with Cloned Object: true Is Original Object's field subj the same with Cloned Object: true Original Object after it is updated: Dan - Physics Cloned Object after updating original object: John - Physics 이 예 에서 복사 할 클래스 Student 에 게 Clonable 인터페이스 와 Object 류 의 clone()방법 을 다시 쓰 라 고 한 다음 에 방법 내부 에서 슈퍼 clone()방법 을 호출 합 니 다.출력 결과 에서 볼 수 있 듯 이 원본 대상 stud 의"name"속성 에 대한 변 화 는 복사 대상 clonedStud 에 영향 을 주지 않 지만 인용 대상 subj 의"name"속성 에 대한 변 화 는 복사 대상 clonedStud 에 영향 을 미친다.3.딥 카피 1.딥 카피 가 무엇 입 니까? 깊이 복사 하면 모든 속성 을 복사 하고 속성 이 가리 키 는 동적 분 배 된 메모 리 를 복사 합 니 다.대상 이 인용 한 대상 과 함께 복사 할 때 깊 은 복사 가 발생 합 니 다.깊 은 복사 보 다 는 얕 은 복사 속도 가 느 리 고 비용 이 많이 든다
위의 그림 에서 SourceObject 는 int 형식의 속성 인'field 1'과 인용 유형 속성 인'refObj 1'(Contained Object 형식의 대상 참조)이 있 습 니 다.SourceObject 를 깊이 복사 할 때 CopiedObject 를 만 들 었 습 니 다."field 1"복사 값 을 포함 하 는 속성"field 2"와"refObj 1"복사 값 을 포함 하 는 참조 형식 속성"refObj 2"가 있 습 니 다.따라서 SourceObject 의"refObj"에 대한 어떠한 변화 도 CopiedObject 에 영향 을 주지 않 습 니 다.
2.딥 복사 어떻게 실현 다음은 심 복 사 를 실현 하 는 예 이다.다만 얕 은 복사 예 에서 약간의 변경 을 했 을 뿐 Subject 와 Copytest 류 는 변 하지 않 았 다
public class Student implements Cloneable {
//
private Subject subj;
private String name;
public Student(String s, String sub) {
name = s;
subj = new Subject(sub);
}
public Subject getSubj() {
return subj;
}
public String getName() {
return name;
}
public void setName(String s) {
name = s;
}
/**
* clone()
*
* @return
*/
public Object clone() {
// , ,
Student s = new Student(name, subj.getName());
return s;
}
}
출력 결 과 는 다음 과 같 습 니 다. Original Object: John - Algebra Cloned Object: John - Algebra Is Original Object the same with Cloned Object: false Is Original Object's field name the same with Cloned Object: true Is Original Object's field subj the same with Cloned Object: false Original Object after it is updated: Dan - Physics Cloned Object after updating original object: John - Algebra clone()방법의 약간의 변 화 를 쉽게 발견 할 수 있다.깊 은 복사 이기 때문에 복사 류 의 대상 을 만들어 야 합 니 다.Student 클래스 에 대상 인용 이 있 기 때문에 Student 클래스 에서 Cloneable 인 터 페 이 스 를 실현 하고 clone 방법 을 다시 써 야 합 니 다.3.직렬 화 를 통 해 심 한 복사 실현 직렬 화 를 통 해 딥 복사 도 가능 하 다.서열 화 는 무엇 을 하 는 것 입 니까?전체 대상 그림 을 영구적 인 저장 파일 에 기록 하고 필요 할 때 읽 어 오 는 것 은 읽 어야 할 때 전체 대상 그림 의 복사 가 필요 하 다 는 것 을 의미한다.이것 이 바로 당신 이 상 대 를 깊이 복사 할 때 진정 으로 필요 한 것 입 니 다.직렬 화 를 통 해 깊이 복사 할 때 대상 그림 의 모든 종 류 를 직렬 화 할 수 있 도록 확보 해 야 합 니 다
public class ColoredCircle implements Serializable {
private int x;
private int y;
public ColoredCircle(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
@Override
public String toString() {
return "x=" + x + ", y=" + y;
}
}
public class DeepCopy {
public static void main(String[] args) throws IOException {
ObjectOutputStream oos = null;
ObjectInputStream ois = null;
try {
//
ColoredCircle c1 = new ColoredCircle(100, 100);
System.out.println("Original = " + c1);
ColoredCircle c2 = null;
//
ByteArrayOutputStream bos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(bos);
//
oos.writeObject(c1);
oos.flush();
ByteArrayInputStream bin = new ByteArrayInputStream(bos.toByteArray());
ois = new ObjectInputStream(bin);
//
c2 = (ColoredCircle) ois.readObject();
//
System.out.println("Copied = " + c2);
//
c1.setX(200);
c1.setY(200);
//
System.out.println("Original = " + c1);
System.out.println("Copied = " + c2);
} catch (Exception e) {
System.out.println("Exception in main = " + e);
} finally {
oos.close();
ois.close();
}
}
}
출력 결 과 는 다음 과 같 습 니 다. Original = x=100, y=100 Copied = x=100, y=100 Original = x=200, y=200 Copied=x=100,y=100 여기 서 다음 과 같은 몇 가지 일 을 해 야 합 니 다.(1)대상 그림 의 모든 클래스 가 직렬 화 되 어 있 는 지 확인 하 십시오.(2)입 출력 흐름 을 만 듭 니 다.(3)이 입 출력 흐름 을 사용 하여 대상 의 입력 과 대상 출력 흐름 을 만 듭 니 다.(4)복사 하고 싶 은 대상 을 대상 의 출력 흐름 에 전달 합 니 다.(5)대상 의 입력 흐름 에서 새로운 대상 을 읽 고 보 낸 대상 의 클래스 로 전환 합 니 다. 이 예 에서,나 는 ColoredCircle 대상 c1 을 만 들 고 그것 을 직렬 화(ByteArray OutputStream 에 기록)했다.그리고 나 서 나 는 이 직렬 화 된 대상 을 반 직렬 화하 고 c2 에 저장 했다.그리고 나 서 나 는 원본 대상 c1 을 수정 했다.그리고 결 과 는 보시 다시 피 c1 은 c2 와 다 르 며 c1 에 대한 어떠한 수정 도 c2 에 영향 을 주지 않 습 니 다.이러한 방식 은 그 자체 의 제한 과 문제 가 있 습 니 다.transient 변 수 를 직렬 화 할 수 없 기 때문에 이 방법 을 사용 하면 transient 변 수 를 복사 할 수 없습니다.
성능 문제 다.socket 을 만 들 고 대상 을 직렬 화 하 며 socket 을 통 해 전송 한 다음 반 직렬 화 합 니 다.이 과정 은 기 존 대상 을 호출 하 는 방법 에 비해 느 립 니 다.그래서 성능 에 있어 서 는 천양지차 가 있 을 수 있 습 니 다.만약 성능 이 당신 의 코드 에 있어 서 매우 중요 하 다 면,이런 방식 을 사용 하지 않 는 것 을 권장 합 니 다.그것 은 Clonable 인 터 페 이 스 를 실현 하 는 방식 으로 깊이 복사 하 는 것 보다 거의 100 배 나 많은 시간 이 걸린다.
4.복사 지연 복사 지연 은 얕 은 복사 와 깊 은 복사 의 조합 으로 실제로 거의 사용 되 지 않 는 다.처음에 대상 을 복사 할 때 속도 가 빠 른 얕 은 복사 본 을 사용 하고 얼마나 많은 대상 이 이 데 이 터 를 공유 하 는 지 계수 기 를 사용 합 니 다.프로그램 이 원본 대상 을 수정 하려 고 할 때 데이터 가 공유 되 는 지 여 부 를 결정 하고 필요 에 따라 깊이 복사 합 니 다. 복사 지연 은 밖에서 보면 깊 은 복사 로 보이 지만 가능 하 다 면 얕 은 복사 속 도 를 이용 할 것 이다.원본 대상 의 인용 이 자주 바 뀌 지 않 을 때 지연 복 사 를 사용 할 수 있 습 니 다.계수기 가 존재 하기 때문에 효율 은 매우 높 지만,단지 상수 급 의 지출 일 뿐이다.그리고 어떤 경우 에는 순환 인용 이 문제 가 될 수 있다.
5.어떻게 선택 합 니까? 대상 의 속성 이 모두 기본 유형 이 라면 얕 은 복사 본 을 사용 할 수 있 지만 대상 이 인용 속성 이 있다 면 구체 적 인 수 요 를 바탕 으로 얕 은 복사 인지 깊 은 복사 인지 선택해 야 한다.내 말 은 대상 의 인용 이 언제든지 바 뀌 지 않 는 다 면 깊 은 복사 본 을 사용 할 필요 가 없고 얕 은 복사 만 사용 하면 된다 는 것 이다.대상 인용 이 자주 바 뀌 면 심 한 복사 본 을 사용 해 야 한다.변 함 없 는 규칙 은 없다.모든 것 은 구체 적 인 수요 에 달 려 있다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
자바의 복사 메커니즘을 깊이 이해하다만약 우리new가 새로운 대상을 낸다면, 하나의 성명으로 인용하고, 그 다음에 다른 성명으로 이전 성명을 인용한다면, 마지막 결과는 이 두 성명의 변수는 같은 대상을 가리키며, 한 곳은 모두 수정될 것이다.만약 우리...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.