java 對象的克?。\克隆和深克隆)
java 對象的克隆
一、對象的淺克隆
(1)需要克隆類需要重寫Object類的clone方法,并且實(shí)現(xiàn)Cloneable接口(標(biāo)識接口,無需實(shí)現(xiàn)任何方法)
(2)當(dāng)需要克隆的對象中維護(hù)著另外一個引用對象,淺克隆不會克隆另外一個引用對下,而是直接復(fù)制維護(hù)的另外一個引用對象的地址。
(3)對象的淺克隆也不會調(diào)用到構(gòu)造方法。
以下為對象的淺克隆的一個例子:
package com.clone; import java.io.Serializable; /** * Description: * 實(shí)現(xiàn)了Cloneable接口,并重寫Object類的clone方法。 * * @author lee * */ public class CloneDemo1 implements Cloneable,Serializable{ //該克隆類封裝的信息 public int id; public String name; public Address address; /** * Desciption: * 默認(rèn)構(gòu)造器 * * */ public CloneDemo1(){} /** * Description: * 初始化id,name的構(gòu)造器 * * @param id id * @param name 名字 * @param address 地址 * */ public CloneDemo1(int id, String name, Address address){ this.id=id; this.name=name; this.address = address; } /** * Descriptin: * 重寫Object類的clone方法。 * if the object's class does not support the Cloneable interface. * Subclasses that override the clone method can also throw this exception * to indicate that an instance cannot be cloned. * * @throws CloneNotSupportedException * */ @Override public Object clone() throws CloneNotSupportedException{ return super.clone(); } /** * Description: * 重寫toString方法 * * @return "id="+id+", name="+name * */ @Override public String toString(){ return "id="+id+", name="+name+", address:"+address.getAddress(); } /** * Description: * 主方法 * * */ public static void main(String[] args) throws CloneNotSupportedException{ CloneDemo1 c1 = new CloneDemo1(1,"c1",new Address("北京")); //c2 復(fù)制了c1的地址,并沒有復(fù)制整個c1對象 CloneDemo1 c2 = c1; //c3 對象的淺克隆,復(fù)制了整個對象 CloneDemo1 c3 = (CloneDemo1)c1.clone(); //當(dāng)對象c1改變其name或者id的時(shí)候,c2也會自動改變。 //因?yàn)閏2只是復(fù)制了c1的地址,并非復(fù)制了c1的整個對象。 //相應(yīng)的c3則不會隨著c1改變而改變,意味著c3將c1整個對象克隆一份出來。 //當(dāng)是,對象的淺克隆不會克隆被克隆對象當(dāng)中的引用對象。 //因此c1改變其中的Address的引用對象時(shí),c2,c3也會跟著改變。 c1.setName("cc"); c1.address.setAddress("上海"); System.out.println(c1+"\n"+c2+"\n"+c3); } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } } /** * Description: * 一個封裝著地址的類 * * @author lee * */ class Address implements Serializable{ public String address; /** * Description: * 默認(rèn)構(gòu)造器 * * */ public Address(){} /** * Description: * 初試化address * * @param address 地址 * */ public Address(String address){ this.address = address; } //address的set和get方法 public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } }
二、對象的深克隆
就是利用對象的輸入輸出流把對象寫到文件上,再讀取對象的信息,這就是對象的深克隆。
由于對象的淺克隆不會克隆被克隆對象其中的引用對象,而是直接復(fù)制其地址。因此,要克隆被克隆對象當(dāng)中的引用類型則需要對象的深克隆。
而對象的深克隆使用的的對象序列化輸入輸出。
代碼如下:
package com.clone; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; /** * Description: * 實(shí)現(xiàn)對象的深克隆 * * @author lee * */ public class CloneDemo2 { /** * Description: * 將對象輸出到一個文件當(dāng)中。 * * @param c 需要被寫到文件當(dāng)中的對象。 * */ public static void writeObject(CloneDemo1 c){ ObjectOutputStream out = null; try{ //將對象輸出在一個object.txt文件當(dāng)中 out = new ObjectOutputStream(new FileOutputStream("./object.txt")); out.writeObject(c); }catch(IOException e){ System.out.println("寫入對象的時(shí)候發(fā)生了錯誤。"); e.printStackTrace(); }finally{ //關(guān)閉資源 try{ out.close(); }catch(IOException e){ e.printStackTrace(); } } } /** * Description: * 從文件中讀取出一個對象來,并返回。 * * @return c 返回一個對象。 * */ public static CloneDemo1 readObject(){ CloneDemo1 c = null; ObjectInputStream input = null; try{ //從object.txt文件中讀取一個對象出來 input = new ObjectInputStream(new FileInputStream("./object.txt")); c = (CloneDemo1)input.readObject(); }catch(IOException | ClassNotFoundException e){ e.printStackTrace(); System.out.println("讀取對象的時(shí)候發(fā)生了錯誤。"); }finally{ //關(guān)閉資源 try{ input.close(); }catch(IOException e){ e.printStackTrace(); } } return c; } /** * Description: * 主方法 * * @throws CloneNotSupportedException * */ public static void main(String[] args) throws CloneNotSupportedException { CloneDemo1 c1 = new CloneDemo1(1,"c1",new Address("北京")); //c2 對象的淺克隆 CloneDemo1 c2 = (CloneDemo1)c1.clone(); //c3對象的深克隆 writeObject(c1); CloneDemo1 c3 = readObject(); //因?yàn)閷ο蟮纳羁寺⊥瑫r(shí)也克隆了被克隆對象維護(hù)的另外一個對象 //所以,當(dāng)c1改變其當(dāng)中的維護(hù)的另外一個對象的時(shí)候,c3不會隨之改變。 //而c2位淺克隆,其維護(hù)的另外一個對象只是復(fù)制了c1維護(hù)的對象的地址,因此會隨著c1的改變而改變。 c1.address.setAddress("上海"); System.out.println(c1+"\n"+c2+"\n"+c3); } }
對象的序列化,是需要實(shí)現(xiàn)Serializable接口的。
感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!
相關(guān)文章
自帶IDEA插件的阿里開源診斷神器Arthas線上項(xiàng)目BUG調(diào)試
這篇文章主要為大家介紹了自帶IDEA插件阿里開源診斷神器Arthas線上項(xiàng)目BUG調(diào)試,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06關(guān)于SpringSecurity簡介以及和Shiro的區(qū)別
這篇文章主要介紹了關(guān)于SpringSecurity簡介以及和Shiro的區(qū)別,在Java應(yīng)用安全領(lǐng)域,Spring Security會成為被首先推崇的解決方案,就像我們看到服務(wù)器就會聯(lián)想到Linux一樣順理成章,需要的朋友可以參考下2023-07-07eclipse創(chuàng)建springboot項(xiàng)目的三種方式總結(jié)
這篇文章主要介紹了eclipse創(chuàng)建springboot項(xiàng)目的三種方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-07-07SpringBoot微服務(wù)注冊分布式Consul的詳細(xì)過程
這篇文章主要介紹了SpringBoot(微服務(wù))注冊分布式Consul,Spring Boot應(yīng)用可以通過向Consul注冊自身來實(shí)現(xiàn)服務(wù)發(fā)現(xiàn)和治理,使得其他服務(wù)可以在Consul中發(fā)現(xiàn)并調(diào)用它,需要的朋友可以參考下2023-04-04詳解Java中的checked異常和unchecked異常區(qū)別
這篇文章主要介紹了詳解Java中的checked異常和unchecked異常區(qū)別,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-02-02SpringBoot實(shí)現(xiàn)excel生成并且通過郵件發(fā)送的步驟詳解
實(shí)際開發(fā)中,特別是在B端產(chǎn)品的開發(fā)中,我們經(jīng)常會遇到導(dǎo)出excel的功能,更進(jìn)階一點(diǎn)的需要我們定期生成統(tǒng)計(jì)報(bào)表,然后通過郵箱發(fā)送給指定的人員,?今天要帶大家來實(shí)現(xiàn)的就是excel生成并通過郵件發(fā)送,需要的朋友可以參考下2023-10-10