經(jīng)典Java面試題的答案——對象拷貝

大家好瘦癌,我是九神省有。這是互聯(lián)網(wǎng)技術(shù)崗的分享專題合武,廢話少說,進(jìn)入正題:

61.為什么要使用克掠畲臁?

想對一個(gè)對象進(jìn)行處理酪术,又想保留原有的數(shù)據(jù)進(jìn)行接下來的操作器瘪,就需要克隆了,Java語言中克隆針對的是類的實(shí)例绘雁。

62.如何實(shí)現(xiàn)對象克孪鹛邸?

有兩種方式:

1). 實(shí)現(xiàn)Cloneable接口并重寫Object類中的clone()方法庐舟;

2). 實(shí)現(xiàn)Serializable接口欣除,通過對象的序列化和反序列化實(shí)現(xiàn)克隆,可以實(shí)現(xiàn)真正的深度克隆挪略,代碼如下:

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class UtilDemo {
  
    private UtilDemo() {        
      throw new AssertionError();    
    }
  
    @SuppressWarnings("unchecked")    
    public static <T extends Serializable> T clone(T obj) throws Exception {        
      ByteArrayOutputStream bout = new ByteArrayOutputStream();        
      ObjectOutputStream oos = new ObjectOutputStream(bout);        
      oos.writeObject(obj);
      
      ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());        
      ObjectInputStream ois = new ObjectInputStream(bin);        
      return (T) ois.readObject();
      
      // 說明:調(diào)用ByteArrayInputStream或ByteArrayOutputStream對象的close方法沒有任何意義        
      // 這兩個(gè)基于內(nèi)存的流只要垃圾回收器清理對象就能夠釋放資源历帚,這一點(diǎn)不同于對外部資源(如文件流)的釋放    
    }
}

下面是測試代碼:

import java.io.Serializable;

/** 
  * 學(xué)生 
  * @author 醬油君 
  * 
  */
class Student implements Serializable {    
  private static final long serialVersionUID = -9102017020286042305L;
  
  private String name;    // 姓名    
  private int age;        // 年齡    
  private Teacher teacher;        // 老師
    
  public Person(String name, int age, Car car) {        
    this.name = name;        
    this.age = age;        
    this.teacher = teacher;    
  }
    
  public String getName() {        
    return name;    
  }
    
  public void setName(String name) {        
    this.name = name;    
  }
    
  public int getAge() {        
    return age;    
  }        
  
  public void setAge(int age) {        
    this.age = age;    
  }
    
  public Teacher getTeacher() {        
    return teacher;    
  }
    
  public void setTeacher(Teacher teacher) {        
    this.teacher = teacher;    
  }
    
  @Override    
  public String toString() {        
    return "Student [name=" + name + ", age=" + age + ", teacher=" + teacher + "]";   
  }
  
}

/** 
    * 老師類 
    * @author 醬油君 
    * 
    */
class Teacher implements Serializable {    
  private static final long serialVersionUID = -5713945027627603702L;
    
  private String teacherName;       // 老師名稱    
  private String skill;       // 老師技能
    
  public Teacher(String teacherName, String skill) {        
    this.teacherName = teacherName;        
    this.skill = skill;    
  }
    
  public String getTeacherName() {        
    return teacherName;    
  }
    
  public void setTeacherName(String teacherName) {        
    this.teacherName = teacherName;    
  }
    
  public int getSkill() {        
    return skill;    
  }       
  
  public void setSkill(String skill) {        
    this.skill = skill;    
  }
    
  @Override    
  public String toString() {        
    return "Teacher [teacherName=" + teacherName + ", skill=" + skill + "]";    
  }
  
}

class CloneTest {
   
  public static void main(String[] args) {        
    try {            
      Student s1 = new Student("郭靖", 33, new Teacher("黃蓉", "黯然銷魂掌"));            
      Student s2 = UtilDemo.clone(s1);   // 深度克隆            
      s2.getTeacher().setSkill("打狗棒法");            
      // 修改克隆的Student對象s2關(guān)聯(lián)的老師對象的技能屬性            
      // 原來的Student對象s1關(guān)聯(lián)的老師不會受到任何影響            
      // 因?yàn)樵诳寺tudent對象時(shí)其關(guān)聯(lián)的老師對象也被克隆了            
      System.out.println(s1);        
    } catch (Exception e) {            
      e.printStackTrace();        
    }    
  }
}

注意:基于序列化和反序列化實(shí)現(xiàn)的克隆不僅僅是深度克隆,更重要的是通過泛型限定杠娱,可以檢查出要克隆的對象是否支持序列化挽牢,這項(xiàng)檢查是編譯器完成的,不是在運(yùn)行時(shí)拋出異常摊求,這種是方案明顯優(yōu)于使用Object類的clone方法克隆對象禽拔。讓問題在編譯的時(shí)候暴露出來總是好過把問題留到運(yùn)行時(shí)。

63.深拷貝和淺拷貝區(qū)別是什么室叉?

淺拷貝只是復(fù)制了對象的引用地址奏赘,兩個(gè)對象指向同一個(gè)內(nèi)存地址,所以修改其中任意的值太惠,另一個(gè)值都會隨之變化磨淌,這就是淺拷貝(例:assign())

深拷貝是將對象及值復(fù)制過來,兩個(gè)對象修改其中任意的值另一個(gè)值不會改變凿渊,這就是深拷貝(例:JSON.parse()和JSON.stringify()梁只,但是此方法無法復(fù)制函數(shù)類型)

文章轉(zhuǎn)載自:
經(jīng)典Java面試題的答案——對象拷貝

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末缚柳,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子搪锣,更是在濱河造成了極大的恐慌秋忙,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件构舟,死亡現(xiàn)場離奇詭異灰追,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)狗超,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進(jìn)店門弹澎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人努咐,你說我怎么就攤上這事苦蒿。” “怎么了渗稍?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵佩迟,是天一觀的道長。 經(jīng)常有香客問我竿屹,道長报强,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任拱燃,我火速辦了婚禮躺涝,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘扼雏。我一直安慰自己坚嗜,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布诗充。 她就那樣靜靜地躺著苍蔬,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蝴蜓。 梳的紋絲不亂的頭發(fā)上碟绑,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天,我揣著相機(jī)與錄音茎匠,去河邊找鬼格仲。 笑死,一個(gè)胖子當(dāng)著我的面吹牛诵冒,可吹牛的內(nèi)容都是我干的凯肋。 我是一名探鬼主播,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼汽馋,長吁一口氣:“原來是場噩夢啊……” “哼侮东!你這毒婦竟也來了圈盔?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤悄雅,失蹤者是張志新(化名)和其女友劉穎驱敲,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體宽闲,經(jīng)...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡众眨,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了容诬。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片娩梨。...
    茶點(diǎn)故事閱讀 39,711評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖放案,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情矫俺,我是刑警寧澤吱殉,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站厘托,受9級特大地震影響友雳,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜铅匹,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一押赊、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧包斑,春花似錦流礁、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至萌抵,卻和暖如春找御,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背绍填。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工霎桅, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人讨永。 一個(gè)月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓滔驶,卻偏偏與公主長得像,于是被迫代替她去往敵國和親卿闹。 傳聞我的和親對象是個(gè)殘疾皇子瓜浸,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,611評論 2 353

推薦閱讀更多精彩內(nèi)容