1. 얕은 사본 및 딥 카피 개념
shallow 사본 (얕은 복제)
복사 된 객체의 모든 변수는 원래 객체와 동일한 값을 포함하지만 다른 객체에 대한 모든 참조는 여전히 원래 객체를 가리 킵니다. 다시 말해, 얕은 복사는 단순히 언급하는 대상이 아니라 고려되는 물체를 복사합니다.
Deep Copy (Deep Cloning)
복사 된 객체의 모든 변수는 다른 객체를 참조하는 변수를 제외하고 원래 객체와 동일한 값을 포함합니다. 다른 개체를 참조하는 변수는 원래 참조 객체 대신 복사 된 새 개체를 가리 킵니다. 다시 말해, 딥 카피는 복사 할 객체가 참조 한 모든 객체를 복사합니다.
2. Java 's Clone () 메소드
clone 클론 방법은 객체의 사본을 복사하여 발신자에게 반환합니다. 일반적으로 Clone () 메소드는 다음과 같습니다.
① 모든 객체 x의 경우 x.clone ()! = x // 복제 된 객체는 원래 객체와 동일한 객체가 아닙니다. getClass () // 클론 객체는 원래 객체의 유형과 동일합니다.
Java의 물체 클론
① 객체의 사본을 얻으려면 객체 클래스의 클론 () 메소드를 사용할 수 있습니다.
② 파생 클래스에서 기본 클래스의 클론 () 메소드를 덮어 쓰고이를 대중으로 선언합니다.
③ 파생 클래스의 클론 () 메소드에서 Super.Clone ()을 호출하십시오.
④ 파생 클래스에서 클로닝 가능한 인터페이스를 구현하십시오.
다음 코드를 참조하십시오.
공개 클래스는 클로닝 가능 {문자열 이름, int. 학생) Super.clone (); // clone ()은 복사 할 객체를 인식합니다. } catch (clonenotsupportedException e) {system.out.println (e.toString ())} public static void main (String [] args) {학생 S1 = 새로운 학생 ( "Zhangsan"); S2 = (학생) S1.Name = "LISI"; System.out.println ( "name ="+s1.name+","+"age ="+s1.age); "name ="+s2.name+","+"age ="; +s2.age); 설명 :
① 파생 클래스에서 객체의 클론 () 메소드를 덮어 쓰면 Super.clone ()를 호출 해야하는 이유는 무엇입니까? 실행 시간에, 객체의 Clone ()은 복사 할 객체를 인식 한 다음이 객체의 공간을 할당하고 객체를 복사하여 원래 객체의 내용을 하나씩 새 개체의 저장 공간에 복사합니다.
java.lang.object 클래스에서 상속 된 클론 () 메소드는 얕은 사본입니다. 다음 코드가 증명할 수 있습니다.
클래스 교수 {문자열 이름; int 연령; 교수 P; String Name, int Age P) {this.age = p = p; .Clone ()} catch (clonenotsupportedException e) {system.out.println (e.toString ()); ) {교수님 (Wangwu), 50); "; = "+s2.p.name+", "+"age = "+s2.p.age); // 학생 1과 2 교수의 출력 결과는 Lisi가되고 나이는 30입니다. }} 그렇다면 우리는 어떻게 깊은 클로닝을 구현해야합니까, 즉 S2를 수정하는 교수는 S1 교수에게 영향을 미치지 않습니까? 코드는 다음과 같이 개선됩니다.
학생 1의 교수가 변하지 않게 만드는 개선 (깊은 클론)
클래스 교수는 {문자열 이름, int. Clone ()} CATH (ClonenOtsupportedException e) {e.toString ()} 공개 클래스 학생 (문자열 이름); int Age, p.name = gen.pection. public 객체 클론; } catch (clonenotsupportedException e) {system.out.println (e.tostring ()) // public static void main; ] Args) {새로운 교수님 (Wangwu), 학생 S1; "Lisi"; S2.p.age = 30; system.out.println ( "name ="+s1.p.name+","+"age ="+s1.p.age); "name ="+s2.p.name+"; "+"age = "+s2.p.age);}} 3. 직렬화를 사용하여 딥 카피를 수행합니다 (주로 더 복잡한 객체의 복제 복사 방법을 다시 작성하지 않고 중단 점 연속 전송 및 기타 기능을 구현할 수도 있습니다).
개체를 스트림에 쓰는 과정은 직렬화 프로세스이지만, Java 프로그래머의 원형에서 "Frozen"또는 "Picking"프로세스라고하며, 그 결과 병렬화 프로세스는 "해동"또는 "Depicking"이라고합니다. 프로세스.
스트림에 쓰여진 것은 객체의 사본이고 원래 객체는 여전히 JVM에 존재한다는 점을 지적해야하므로 "피클에 피클로 뽑는"것은 객체의 사본 일 뿐이며 Java 피클은 여전히 가능합니다. 신선하십시오.
Java 언어로 객체를 깊이 복사하면 객체가 직렬화 가능한 인터페이스를 먼저 구현 한 다음 객체 (실제로 객체의 사본 만)를 스트림 (피클에 절인)에 쓰고 스트림에서 읽을 수 있습니다. 피클은 물체를 재구성 할 수 있습니다.
다음은 딥 카피 소스 코드입니다.
공개 객체 DeepClone () {// 객체를 스트림에 쓴다. Bo.tobytearray ()) ObjectInputStream (BI); 이를 수행하는 전제는 객체 내의 객체와 참조 된 모든 객체가 직렬화 가능하다는 것입니다. 직렬화 할 수없는 객체 또는 속성을 일시적으로 설정할 수 있는지 신중하게 검토하여 복사 프로세스에서 제외해야합니다. . 밖의. 위의 예제 코드는 다음과 같이 개선됩니다.
교사는 Serialized {문자열 이름, int Age; 연령; 교사 T; // 학생 1과 학생 2의 기준 값은 동일합니다. 공개 학생 (문자열 이름, int Age, T) BytearRayoutoutStream BO = ObjectOutStream (BO); New ObjectInputStream (Bi); 18, t); 학생) s1.deepclone (); 이름 = "+s1.t.name+", "+"age = "+s1.t.age);}}