자바 향상 편 (5) - 직렬 화 실현 대상 의 복사 사용
질문
우 리 는 먼저 다음 코드 를 본다.
public class Person implements Cloneable{
/** **/
private String name;
/** **/
private Email email;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Email getEmail() {
return email;
}
public void setEmail(Email email) {
this.email = email;
}
public Person(String name,Email email){
this.name = name;
this.email = email;
}
public Person(String name){
this.name = name;
}
protected Person clone() {
Person person = null;
try {
person = (Person) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return person;
}
}
public class Client {
public static void main(String[] args) {
//
Email email = new Email(" "," 12:30 ...");
Person person1 = new Person(" ",email);
Person person2 = person1.clone();
person2.setName(" ");
Person person3 = person1.clone();
person3.setName(" ");
System.out.println(person1.getName() + " :" + person1.getEmail().getContent());
System.out.println(person2.getName() + " :" + person2.getEmail().getContent());
System.out.println(person3.getName() + " :" + person3.getEmail().getContent());
}
}
--------------------
Output:
: 12:30 ...
: 12:30 ...
: 12:30 ...
이 프로그램 에서 먼저 메 일 한 통 을 정의 한 다음 에 이 메 일 을 장 삼, 이사, 왕 오 세 사람 에 게 보 냅 니 다. 그들 은 같은 메 일 을 사용 하고 이름 만 다 르 기 때문에 장 삼 을 사용 하여 이 대상 류 를 복사 한 다음 에 이름 을 바 꾸 면 됩 니 다.프로그램 이 여기까지 온 것 은 틀 리 지 않 았 습 니 다. 그러나 만약 에 우리 가 3 분 전에 30 분 전에 도착 해 야 한다 면 메 일의 내용 을 수정 하 는 것 입 니 다.
public class Client {
public static void main(String[] args) {
//
Email email = new Email(" "," 12:30 ...");
Person person1 = new Person(" ",email);
Person person2 = person1.clone();
person2.setName(" ");
Person person3 = person1.clone();
person3.setName(" ");
person1.getEmail().setContent(" 12:00 ...");
System.out.println(person1.getName() + " :" + person1.getEmail().getContent());
System.out.println(person2.getName() + " :" + person2.getEmail().getContent());
System.out.println(person3.getName() + " :" + person3.getEmail().getContent());
}
}
여기 서도 장 삼 이라는 대상 을 이용 하여 이사, 왕 오 에 대한 복사 본 을 실현 하고 마지막 으로 장 삼 의 메 일 내용 을 오늘 12 시 부터 2 회의실 까지 회의 에 참석 하 십시오.하지만 결 과 는:
: 12:00 ...
: 12:00 ...
: 12:00 ...
여기 서 우 리 는 왜 이사 와 왕 오 의 메 일 내용 도 바 뀌 었 는 지 의 심 스 러 웠 다.30 분 일찍 오 라 고 하면 의견 이 있 을 거 야!
사실 문제 가 발생 하 는 관건 은 clone () 방법 에 있 습 니 다. 우 리 는 이 clone () 방법 이 Object 류 의 clone () 방법 을 사용 하 는 것 이라는 것 을 알 고 있 습 니 다. 그러나 이 방법 에 결함 이 존재 합 니 다. 대상 의 모든 속성 을 복사 하지 않 고 선택 적 인 복사 가 있 습 니 다. 기본 규칙 은 다음 과 같 습 니 다.
1. 기본 유형
변수 가 기본 적 인 유형 이 라면 int, float 등 값 을 복사 합 니 다.
2. 대상
변수 가 인 스 턴 스 대상 이 라면 주소 인용 을 복사 합 니 다. 즉, 이때 새 대상 과 원래 대상 은 공용 인 스 턴 스 변수 입 니 다.
3. String 문자열
변수 가 String 문자열 이면 주소 참조 복사.그러나 수정 할 때 문자열 풀 에서 새로운 문자열 을 다시 생 성 합 니 다. 원래 의 자색 도성 대상 은 변 하지 않 습 니 다.
위의 규칙 을 바탕 으로 우 리 는 문제 의 소 재 를 쉽게 발견 할 수 있다. 그들 세 사람 은 한 대상 을 공용 하고 장 삼 은 이 메 일의 내용 을 수정 하면 이사 와 왕 오 도 수정 하기 때문에 위의 상황 이 발생 한다.이러한 상황 에 대해 우 리 는 해결 할 수 있 습 니 다. clone () 방법 에서 대상 을 새로 만 든 다음 에 이 대상 을 세 번 인용 하면 됩 니 다.
protected Person clone() {
Person person = null;
try {
person = (Person) super.clone();
person.setEmail(new Email(person.getEmail().getObject(),person.getEmail().getContent()));
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return person;
}
따라서 얕 은 복사 본 은 자바 가 제공 하 는 간단 한 복사 메커니즘 일 뿐 직접 사용 하기 불편 하 다.
위의 해결 방안 에 아직도 문제 가 존재 한다. 만약 에 우리 시스템 에 대량의 대상 이 복사 로 생 성 된다 면 우리 가 모든 유형 에 clone () 방법 을 쓰 고 깊 은 복사 도 해 야 한다. 대량의 대상 을 새로 만들어 야 한다. 이 공 사 는 매우 크다. 여기 서 우 리 는 직렬 화 를 이용 하여 대상 의 복사 도 실현 할 수 있다.
2. 직렬 화 를 이용 하여 대상 의 복사
어떻게 서열 화 를 이용 하여 대상 의 복사 본 을 완성 합 니까?메모리 에서 바이트 흐름 을 통 해 복사 하 는 것 은 비교적 쉽게 이 루어 진다.모 대상 을 하나의 바이트 흐름 에 기록 하고 바이트 흐름 에서 읽 으 면 새로운 대상 을 만 들 수 있 습 니 다. 또한 이 새로운 대상 과 모 대상 사이 에는 인용 공유 문제 가 존재 하지 않 고 대상 의 깊 은 복사 를 진정 으로 실현 할 수 있 습 니 다.
public class CloneUtils {
@SuppressWarnings("unchecked")
public static <T extends Serializable> T clone(T obj){
T cloneObj = null;
try {
//
ByteArrayOutputStream out = new ByteArrayOutputStream();
ObjectOutputStream obs = new ObjectOutputStream(out);
obs.writeObject(obj);
obs.close();
// , ,
ByteArrayInputStream ios = new ByteArrayInputStream(out.toByteArray());
ObjectInputStream ois = new ObjectInputStream(ios);
//
cloneObj = (T) ois.readObject();
ois.close();
} catch (Exception e) {
e.printStackTrace();
}
return cloneObj;
}
}
이 도구 류 를 사용 하 는 대상 은 Serializable 인 터 페 이 스 를 실현 해 야 합 니 다. 그렇지 않 으 면 복 제 를 실현 할 방법 이 없습니다.
public class Person implements Serializable{
private static final long serialVersionUID = 2631590509760908280L;
..................
// clone()
}
public class Email implements Serializable{
private static final long serialVersionUID = 1267293988171991494L;
....................
}
따라서 이 도구 류 를 사용 하 는 대상 은 Serializable 인터페이스 만 실현 하면 대상 의 복 제 를 실현 할 수 있 으 며, Cloneable 인 터 페 이 스 를 계승 하여 clone () 방법 을 실현 할 필요 가 없다.
public class Client {
public static void main(String[] args) {
//
Email email = new Email(" "," 12:30 ...");
Person person1 = new Person(" ",email);
Person person2 = CloneUtils.clone(person1);
person2.setName(" ");
Person person3 = CloneUtils.clone(person1);
person3.setName(" ");
person1.getEmail().setContent(" 12:00 ...");
System.out.println(person1.getName() + " :" + person1.getEmail().getContent());
System.out.println(person2.getName() + " :" + person2.getEmail().getContent());
System.out.println(person3.getName() + " :" + person3.getEmail().getContent());
}
}
-------------------
Output:
: 12:00 ...
: 12:30 ...
: 12:30 ...
기 초 를 공 고 히 하고 기술 을 향상 시 키 며 어려움 을 두려워 하지 않 고 고봉 등반!!!!!!
참고 문헌 인 진 소 파
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Is Eclipse IDE dying?In 2014 the Eclipse IDE is the leading development environment for Java with a market share of approximately 65%. but ac...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.