Java의 객체에 대한 딥 클론 및 얕은 클론 소개
Υ연한 복제(연한 복제)
복사된 대상의 모든 변수는 원래의 대상과 같은 값을 포함하고, 모든 다른 대상에 대한 인용은 여전히 원래의 대상을 가리킨다.얕은 복제는 고려된 대상만 복제할 뿐 인용된 대상은 복제하지 않는다는 얘기다.
⑵ 딥 복제(딥 복제)
복사된 대상의 모든 변수는 다른 대상을 인용하는 변수를 제외하고 원래의 대상과 같은 값을 포함한다.다른 대상을 인용하는 변수는 복사된 새로운 대상을 가리키며, 더 이상 원래의 인용된 대상이 아니다.다시 말하면 복제할 대상이 인용한 대상을 깊이 복제한 것이다.
2. Java의 clone () 메서드
Υclone 방법으로 객체를 복사하여 호출자에게 반환합니다.일반적으로 clone () 메서드는 다음과 같습니다.
① 모든 대상x에 x.clone ()!=x//클론 객체가 원래 객체와 동일하지 않음
② 모든 객체 x에는 x.clone()이 있습니다.getClass () = x.getClass ()//클론 객체는 원래 객체 유형과 동일합니다.
③ 객체 x의 equals () 방법이 적절하게 정의된 경우 x.clone ().equals(x)는 성립되어야 한다.
⑵ Java의 객체 클론
① 객체의 복사본을 얻기 위해 Object 클래스의 clone () 방법을 사용할 수 있습니다.
② 파생 클래스에서 기본 클래스를 덮어쓰는 clone () 방법은public라고 합니다.
③ 파생 클래스의 clone () 방법에서 super를 호출합니다.clone().
④ 파생 클래스에서 Cloneable 인터페이스를 구현합니다.
다음 코드를 참조하십시오.
public class Student implements Cloneable
{
String name;
int age;
Student(String name,int age)
{
this.name=name;
this.age=age;
}
public Object clone()
{
Object o=null;
try
{
o=(Student)super.clone();//Object clone() 。
}
catch(CloneNotSupportedException e)
{
System.out.println(e.toString());
}
return o;
}
public static void main(String[] args)
{
Student s1=new Student("zhangsan",18);
Student s2=(Student)s1.clone();
s2.name="lisi";
s2.age=20;
// 2 , 1 。
System.out.println("name="+s1.name+","+"age="+s1.age);
System.out.println("name="+s2.name+","+"age="+s2.age);
}
}
설명:① 왜 우리가 파생 클래스에서 Object의 clone () 방법을 덮어쓸 때 반드시 슈퍼를 호출해야 하는가.클론()은요?실행 시간에, Object의 clone () 은 복사할 대상이 무엇인지 식별하고, 이 대상에 공간을 분배하고, 대상의 복사를 진행하며, 원본 대상의 내용을 일일이 새로운 대상의 저장 공간에 복사합니다.
② 자바에서 상속한다.lang.Object 클래스의clone () 방법은 얕은 복사입니다.다음 코드는 이를 증명할 수 있다.
class Professor
{
String name;
int age;
Professor(String name,int age)
{
this.name=name;
this.age=age;
}
}
public class Student implements Cloneable
{
String name;// 。
int age;
Professor p;// 1 2 。
Student(String name,int age,Professor p)
{
this.name=name;
this.age=age;
this.p=p;
}
public Object clone()
{
Student o=null;
try
{
o=(Student)super.clone();
}
catch(CloneNotSupportedException e)
{
System.out.println(e.toString());
}
o.p=(Professor)p.clone();
return o;
}
public static void main(String[] args)
{
Professor p=new Professor("wangwu",50);
Student s1=new Student("zhangsan",18,p);
Student s2=(Student)s1.clone();
s2.p.name="lisi";
s2.p.age=30;
System.out.println("name="+s1.p.name+","+"age="+s1.p.age);
System.out.println("name="+s2.p.name+","+"age="+s2.p.age);
// 1 2 lisi,age 30。
}
}
그러면 어떻게 심층적인 복제, 즉 s2를 수정한 교수가 s1의 교수에게 영향을 주지 않도록 실현해야 합니까?코드 개선은 다음과 같습니다.향상된 Professor 1 변경 사항 없음(심층 복제)
class Professor implements Cloneable
{
String name;
int age;
Professor(String name,int age)
{
this.name=name;
this.age=age;
}
public Object clone()
{
Object o=null;
try
{
o=super.clone();
}
catch(CloneNotSupportedException e)
{
System.out.println(e.toString());
}
return o;
}
}
public class Student implements Cloneable
{
String name;
int age;
Professor p;
Student(String name,int age,Professor p)
{
this.name=name;
this.age=age;
this.p=p;
}
public Object clone()
{
Student o=null;
try
{
o=(Student)super.clone();
}
catch(CloneNotSupportedException e)
{
System.out.println(e.toString());
}
//
o.p=(Professor)p.clone();
return o;
}
public static void main(String[] args)
{
Professor p=new Professor("wangwu",50);
Student s1=new Student("zhangsan",18,p);
Student s2=(Student)s1.clone();
s2.p.name="lisi";
s2.p.age=30;
// 1 。
System.out.println("name="+s1.p.name+","+"age="+s1.p.age);
System.out.println("name="+s2.p.name+","+"age="+s2.p.age);
}
}
3. 직렬화를 이용하여 심층 복제를 한다(주로 비교적 복잡한 대상의 심층 복제를 다시 쓰는 clone () 방법을 피하기 위해 프로그램이 단점 리셋 등 기능을 실현할 수 있다)대상을 흐름에 쓰는 과정은 직렬화(Serilization) 과정이지만 자바 프로그래머들 사이에서는'냉동'또는'절임(picking)'과정이라고 매우 형상적으로 불린다.대상을 흐름에서 읽는 병행화(Deserialization) 과정을'해동'또는'신선도(depicking)'과정이라고 한다.
반드시 지적해야 할 것은 흐름에 쓰인 것은 대상의 복사본이고 원래의 대상은 여전히 JVM에 존재하기 때문에'절인 채소'는 대상의 복사본일 뿐이고 자바절인 채소는 신선할 수 있다.
자바 언어에서 하나의 대상을 깊이 복제하면 항상 먼저 대상을 Serializable 인터페이스를 실현한 다음에 대상(실제로는 대상의 복사본일 뿐이다)을 하나의 흐름에 쓴 다음에 흐름에서 읽으면 대상을 재건할 수 있다.
다음은 심층 복사 소스 코드입니다.
public Object deepClone()
{
//
ByteArrayOutoutStream bo=new ByteArrayOutputStream();
ObjectOutputStream oo=new ObjectOutputStream(bo);
oo.writeObject(this);
//
ByteArrayInputStream bi=new ByteArrayInputStream(bo.toByteArray());
ObjectInputStream oi=new ObjectInputStream(bi);
return(oi.readObject());
}
이렇게 하는 전제는 대상과 대상 내부에 인용된 모든 대상이 직렬화되는 것이다. 그렇지 않으면 직렬화되지 않는 대상이나 속성이transient로 설정될 수 있는지 자세히 고찰하여 복제 과정에서 제외해야 한다.상례 코드의 개선은 다음과 같다.
class Teacher implements Serializable{
String name;
int age;
public void Teacher(String name,int age){
this.name=name;
this.age=age;
}
}
public class Student implements Serializable{
String name;//
int age;
Teacher t;// 1 2 。
public void Student(String name,int age,Teacher t){
this.name=name;
this.age=age;
this.p=p;
}
public Object deepClone() throws IOException,
OptionalDataException,ClassNotFoundException{//
ByteArrayOutoutStream bo=new ByteArrayOutputStream();
ObjectOutputStream oo=new ObjectOutputStream(bo);
oo.writeObject(this);//
ByteArrayInputStream bi=new ByteArrayInputStream(bo.toByteArray());
ObjectInputStream oi=new ObjectInputStream(bi);
return(oi.readObject());
}
public static void main(String[] args){
Teacher t=new Teacher("tangliang",30);
Student s1=new Student("zhangsan",18,t);
Student s2=(Student)s1.deepClone();
s2.t.name="tony";
s2.t.age=40;
// 1
System.out.println("name="+s1.t.name+","+"age="+s1.t.age);
}
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Java의 객체에 대한 딥 클론 및 얕은 클론 소개복사된 대상의 모든 변수는 원래의 대상과 같은 값을 포함하고, 모든 다른 대상에 대한 인용은 여전히 원래의 대상을 가리킨다.얕은 복제는 고려된 대상만 복제할 뿐 인용된 대상은 복제하지 않는다는 얘기다. 복사된 대상의...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.