Java實現(xiàn)克隆的三種方式實例總結(jié)
本文實例講述了Java實現(xiàn)克隆的三種方式。分享給大家供大家參考,具體如下:
1、淺復(fù)制(淺克隆)這種淺復(fù)制,其實也就是把被復(fù)制的這個對象的一些變量值拿過來了。最后生成student2還是一個新的對象。
public class CloneTest1
{
public static void main(String[] args) throws Exception
{
Student1 student = new Student1();
student.setAge(24);
student.setName("niesong");
Student1 student2 = (Student1)student.clone();
//這個是調(diào)用下面的那個方法,然后把這個這個對象Clone到student
System.out.println("Age:" + student2.getAge() + " " + "Name:" + student2.getName());
System.out.println("---------------------");
student2.setAge(23);
//克隆后得到的是一個新的對象,所以重新寫的是student2這個對象的值
System.out.println(student.getAge());
System.out.println(student2.getAge());
}
}
//克隆的對象必須實現(xiàn)Cloneable這個接口,而且需要重寫clone方法
class Student1 implements Cloneable
{
private int age;
//定義為private說明這個成員變量只能被被當(dāng)前類中訪問,如果外部需要獲得,那么就只能通過getAge方法進行獲取
private String name;
public int getAge()
{
return age;
}
public void setAge(int age)
{
this.age = age;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
@Override
public Object clone() throws CloneNotSupportedException
{
Object object = super.clone();
return object;
}
}
運行結(jié)果:

2、深復(fù)制(情況1使用的是在克隆的時候手動進行深克隆)
public class CloneTest2
{
public static void main(String[] args) throws Exception
{
Teacher teacher = new Teacher();
teacher.setAge(40);
teacher.setName("teacher zhang");
Student2 student2 = new Student2();
student2.setAge(14);
student2.setName("lisi");
student2.setTeacher(teacher);
Student2 student3 = (Student2)student2.clone();
//這里是深復(fù)制,所以這時候Student2中的teacher就是teacher這個對象的一個復(fù)制,就和student3是student2的一個復(fù)制
//所以下面teacher.setName只是對他原來的這個對象更改,但是復(fù)制的那個并沒有更改
System.out.println(student3.getAge());
System.out.println(student3.getName());
System.out.println(student3.getTeacher().getAge());
teacher.setName("teacher niesong");//不會又任何影響
System.out.println(student3.getTeacher().getName());
}
}
class Student2 implements Cloneable
{
private int age;
private String name;
private Teacher teacher;
public int getAge()
{
return age;
}
public void setAge(int age)
{
this.age = age;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public Teacher getTeacher()
{
return teacher;
}
public void setTeacher(Teacher teacher)
{
this.teacher = teacher;
}
@Override
public Object clone() throws CloneNotSupportedException
{
//這一步返回的這個student2還只是一個淺克隆,
Student2 student2 = (Student2)super.clone();
//然后克隆的過程中獲得這個克隆的student2,然后調(diào)用這個getTeacher這個方方法得到這個Teacher對象。然后實現(xiàn)克隆。在設(shè)置到這個student2中的Teacher。
//這樣實現(xiàn)了雙層克隆使得那個teacher對象也得到了復(fù)制。
student2.setTeacher((Teacher)student2.getTeacher().clone());
//雙層克隆使得那個teacher對象也得到了復(fù)制
return student2;
}
}
class Teacher implements Cloneable
{
private int age;
private String name;
public int getAge()
{
return age;
}
public void setAge(int age)
{
this.age = age;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
@Override
public Object clone() throws CloneNotSupportedException
{
return super.clone();
}
}
運行結(jié)果:

3、利用serializable實現(xiàn)深復(fù)制(這個是利用Serializable,利用序列化的方式來實現(xiàn)深復(fù)制(深克?。?,在其中利用了Io流的方式將這個對象寫到IO流里面,然后在從IO流里面讀取,這樣就實現(xiàn)了一個復(fù)制,然后實現(xiàn)序列化的這個會將引用的那個對象也一并進行深復(fù)制,這樣就實現(xiàn)了這個機制,同時在IO里面讀取數(shù)據(jù)的時候還使用了裝飾者模式)
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class CloneTest3
{
public static void main(String[] args) throws Exception
{
Teacher3 teacher3 = new Teacher3();
teacher3.setAge(23);
teacher3.setName("niesong");
Student3 student3 = new Student3();
student3.setAge(50);
student3.setName("wutao");
student3.setTeacher3(teacher3);
Student3 ss = (Student3)student3.deepCopt();
System.out.println(ss.getAge());
System.out.println(ss.getName());
System.out.println("---------------------");
System.out.println(ss.getTeacher3().getAge());
System.out.println(ss.getTeacher3().getName());
System.out.println("-----------------------");
ss.getTeacher3().setAge(7777);
ss.getTeacher3().setName("hhhhh");
System.out.println(teacher3.getAge());
System.out.println(teacher3.getName());
//雖然上面的已經(jīng)改了,但是改的是那個復(fù)制對象后的那個里面的,然后那個原來的那個里面的并沒有改,下面驗證:::
System.out.println("-----------------");
System.out.println(ss.getTeacher3().getAge());
System.out.println(ss.getTeacher3().getName());
}
}
class Teacher3 implements Serializable
{
// 上面的那個警告可以直接消除,除了使用在設(shè)置中不顯示這個警告,還可以使用下面的這兩條語句中的任何一條語句
// 這個serialVersionUID為了讓該類別Serializable向后兼容
// private static final long serialVersionUID = 1L;
// private static final long serialVersionUID = 8940196742313994740L;
private int age;
private String name;
public int getAge()
{
return age;
}
public void setAge(int age)
{
this.age = age;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
}
class Student3 implements Serializable
{
private static final long serialVersionUID = 1L;
private int age;
private String name;
private Teacher3 teacher3;
public int getAge()
{
return age;
}
public void setAge(int age)
{
this.age = age;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public Teacher3 getTeacher3()
{
return teacher3;
}
public void setTeacher3(Teacher3 teacher3)
{
this.teacher3 = teacher3;
}
//使得序列化student3的時候也會將teacher序列化
public Object deepCopt()throws Exception
{
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
//將當(dāng)前這個對象寫到一個輸出流當(dāng)中,,因為這個對象的類實現(xiàn)了Serializable這個接口,所以在這個類中
//有一個引用,這個引用如果實現(xiàn)了序列化,那么這個也會寫到這個輸出流當(dāng)中
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return ois.readObject();
//這個就是將流中的東西讀出類,讀到一個對象流當(dāng)中,這樣就可以返回這兩個對象的東西,實現(xiàn)深克隆
}
}
運行結(jié)果:

更多java相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《Java面向?qū)ο蟪绦蛟O(shè)計入門與進階教程》、《Java數(shù)據(jù)結(jié)構(gòu)與算法教程》、《Java操作DOM節(jié)點技巧總結(jié)》、《Java文件與目錄操作技巧匯總》和《Java緩存操作技巧匯總》
希望本文所述對大家java程序設(shè)計有所幫助。
相關(guān)文章
Spring?Boot如何排除自動加載數(shù)據(jù)源
這篇文章主要介紹了Spring?Boot如何排除自動加載數(shù)據(jù)源,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-12-12
詳談Array和ArrayList的區(qū)別與聯(lián)系
下面小編就為大家?guī)硪黄斦凙rray和ArrayList的區(qū)別與聯(lián)系。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-06-06
Java的Struts框架中登陸功能的實現(xiàn)和表單處理器的使用
這篇文章主要介紹了Java的Struts框架中登陸功能的實現(xiàn)和表單處理器的使用,Struts框架是Java的SSH三大web開發(fā)框架之一,需要的朋友可以參考下2015-12-12
如何解決maven搭建一直處于running:..狀態(tài)問題
在使用Maven搭建項目時,有時會遇到一直處于加載狀態(tài)的情況,通過修改設(shè)置可以解決這個問題,具體步驟為:1. 打開File->Settings->Build, Execution, Deployment->Maven->running,然后在VMOptions中填寫"-DarchetypeCatalog=internal"2024-09-09
詳解SpringBoot Controller接收參數(shù)的幾種常用方式
這篇文章主要介紹了詳解SpringBoot Controller接收參數(shù)的幾種常用方式,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10

