最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

實例分析java對象中淺克隆和深克隆

 更新時間:2018年10月10日 15:46:08   投稿:laozhang  
在本篇文章中我們給大家分享了關于java對象中淺克隆和深克隆的相關知識點和相關代碼內(nèi)容,有興趣的朋友們學習下。

引言:

在Object基類中,有一個方法叫clone,產(chǎn)生一個前期對象的克隆,克隆對象是原對象的拷貝,由于引用類型的存在,有深克隆和淺克隆之分,若克隆對象中存在引用類型的屬性,深克隆會將此屬性完全拷貝一份,而淺克隆僅僅是拷貝一份此屬性的引用。首先看一下容易犯的幾個小問題

clone方法是Object類的,并不是Cloneable接口的,Cloneable只是一個標記接口,標記接口是用用戶標記實現(xiàn)該接口的類具有某種該接口標記的功能,常見的標記接口有三個:Serializable、Cloneable、RandomAccess,沒有實現(xiàn)Cloneable接口,那么調(diào)用clone方法就會爆出CloneNotSupportedException異常。

Object類中的clone方法是protected修飾的,這就表明我們在子類中不重寫此方法,就在子類外無法訪問,因為這個protected權限是僅僅能在Object所在的包和子類能訪問的,這也驗證了子類重寫父類方法權限修飾符可以變大但不能變小的說法。

protected native Object clone() throws CloneNotSupportedException;

重寫clone方法,內(nèi)部僅僅是調(diào)用了父類的clone方法,其實是為了擴大訪問權限,當然你可以把protected改為public,以后再繼承就不用重寫了。當然只是淺克隆的clone函數(shù),深克隆就需要修改了。

@Override  
protected Object clone() throws CloneNotSupportedException {    
 return super.clone();
}

屬性是String的情況,String也是一個類,那String引用類型嗎?String的表現(xiàn)有的像基本類型,歸根到底就是因為String不可改變,克隆之后倆個引用指向同一個String,但當修改其中的一個,改的不是String的值,卻是新生成一個字符串,讓被修改的引用指向新的字符串。外表看起來就像基本類型一樣。

淺克隆:

淺克隆就是引用類型的屬性無法完全復制,類User中包含成績屬性Mark,Mark是由Chinese和math等等組成的,淺克隆失敗的例子

class Mark{
  private int chinese;
  private int math;
  public Mark(int chinese, int math) {
    this.chinese = chinese;
    this.math = math;
  }
 
  public void setChinese(int chinese) {
    this.chinese = chinese;
  }
 
  public void setMath(int math) {
    this.math = math;
  }
 
  @Override
  public String toString() {
    return "Mark{" +
        "chinese=" + chinese +
        ", math=" + math +
        '}';
  }
}
public class User implements Cloneable{
  private String name;
  private int age;
  private Mark mark;
 
  public User(String name, int age,Mark mark) {
    this.name = name;
    this.age = age;
    this.mark = mark;
  }
 
  @Override
  public String toString() {
    return "User{" +
        "name='" + name + '\'' +
        ", age=" + age +
        ", mark=" + mark +
        '}';
  }
 
  @Override
  protected Object clone() throws CloneNotSupportedException {
    return super.clone();
  }
 
  public static void main(String[] args) throws CloneNotSupportedException {
    Mark mark = new Mark(100,99);
    User user = new User("user",22,mark);
    User userClone = (User) user.clone();
    System.out.println("原user:"+user);
    System.out.println("克隆的user:"+userClone);
    //修改引用類型的mark屬性
    user.mark.setMath(60);
    System.out.println("修改后的原user:"+user);
    System.out.println("修改后的克隆user:"+userClone);
  }
}

輸出結果為:   

原user:User{name='user', age=22, mark=Mark{chinese=100, math=99}}
克隆的user:User{name='user', age=22, mark=Mark{chinese=100, math=99}}
修改后的原user:User{name='user', age=22, mark=Mark{chinese=100, math=60}}
修改后的克隆user:User{name='user', age=22, mark=Mark{chinese=100, math=60}}

很清楚的看到user的mark更改后,被克隆的user也修改了。而要想不被影響,就需要深克隆了。

深克?。?/strong>

方式一:clone函數(shù)的嵌套調(diào)用

既然引用類型無法被完全克隆,那將引用類型也實現(xiàn)Cloneable接口重寫clone方法,在User類中的clone方法調(diào)用屬性的克隆方法,也就是方法的嵌套調(diào)用

class Mark implements Cloneable{
  private int chinese;
  private int math;
  public Mark(int chinese, int math) {
    this.chinese = chinese;
    this.math = math;
  }
  public void setChinese(int chinese) {
    this.chinese = chinese;
  }
  public void setMath(int math) {
    this.math = math;
  }
  @Override
  protected Object clone() throws CloneNotSupportedException {
    return super.clone();
  }
  @Override
  public String toString() {
    return "Mark{" +
        "chinese=" + chinese +
        ", math=" + math +
        '}';
  }
}
public class User implements Cloneable{
  private String name;
  private int age;
  private Mark mark;
 
  public User(String name, int age,Mark mark) {
    this.name = name;
    this.age = age;
    this.mark = mark;
  }
 
  @Override
  public String toString() {
    return "User{" +
        "name='" + name + '\'' +
        ", age=" + age +
        ", mark=" + mark +
        '}';
  }
 
  @Override
  protected Object clone() throws CloneNotSupportedException {
    User user = (User) super.clone();
    user.mark = (Mark) this.mark.clone();
    return user;
  }
 
  public static void main(String[] args) throws CloneNotSupportedException {
    Mark mark = new Mark(100,99);
    User user = new User("user",22,mark);
    User userClone = (User) user.clone();
    System.out.println("原user:"+user);
    System.out.println("克隆的user:"+userClone);
    //修改引用類型的mark屬性
    user.mark.setMath(60);
    System.out.println("修改后的原user:"+user);
    System.out.println("修改后的克隆user:"+userClone);
  }
}

輸出結果為: 

原user:User{name='user', age=22, mark=Mark{chinese=100, math=99}}
克隆的user:User{name='user', age=22, mark=Mark{chinese=100, math=99}}
修改后的原user:User{name='user', age=22, mark=Mark{chinese=100, math=60}}
修改后的克隆user:User{name='user', age=22, mark=Mark{chinese=100, math=99}}

方式二:序列化

上一種方法已經(jīng)足夠滿足我們的需要,但是如果類之間的關系很多,或者是有的屬性是數(shù)組呢,數(shù)組可無法實現(xiàn)Cloneable接口(我們可以在clone方法中手動復制數(shù)組),但是每次都得手寫clone方法,很麻煩,而序列化方式只需要給每個類都實現(xiàn)一個Serializable接口,也是標記接口,最后同序列化和反序列化操作達到克隆的目的(包括數(shù)組的復制)。序列化和反序列化的知識請參照下一篇

import java.io.*;
class Mark implements Serializable {
  private int chinese;
  private int math;
  public Mark(int chinese, int math) {
    this.chinese = chinese;
    this.math = math;
}
  public void setChinese(int chinese) {
    this.chinese = chinese;
  }
  public void setMath(int math) {
    this.math = math;
  }
  @Override
  public String toString() {
    return "Mark{" +
        "chinese=" + chinese +
        ", math=" + math +
        '}';
  }
}
public class User implements Serializable{
  private String name;
  private int age;
  private Mark mark;
 
  public User(String name, int age,Mark mark) {
    this.name = name;
    this.age = age;
    this.mark = mark;
  }
 
  @Override
  public String toString() {
    return "User{" +
        "name='" + name + '\'' +
        ", age=" + age +
        ", mark=" + mark +
        '}';
  }
  public static void main(String[] args) throws IOException, ClassNotFoundException {
    Mark mark = new Mark(100,99);
    User user = new User("user",22,mark);
 
    ByteArrayOutputStream bo = new ByteArrayOutputStream();
    ObjectOutputStream oo = new ObjectOutputStream(bo);
    oo.writeObject(user);//序列化
    ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
    ObjectInputStream oi = new ObjectInputStream(bi);
    User userClone = (User) oi.readObject();//反序列化
 
    System.out.println("原user:"+user);
    System.out.println("克隆的user:"+userClone);
    user.mark.setMath(59);
    System.out.println("修改后的原user:"+user);
    System.out.println("修改后的克隆user:"+userClone);
  }
}

輸出結果:

原user:User{name='user', age=22, mark=Mark{chinese=100, math=99}}
克隆的user:User{name='user', age=22, mark=Mark{chinese=100, math=99}}
修改后的原user:User{name='user', age=22, mark=Mark{chinese=100, math=60}}
修改后的克隆user:User{name='user', age=22, mark=Mark{chinese=100, math=99}}

帶數(shù)組屬性的克隆

import java.io.*;
import java.util.Arrays;
 
public class User implements Serializable{
  private String name;
  private int age;
  private int[] arr;
 
  public User(String name, int age, int[] arr) {
    this.name = name;
    this.age = age;
    this.arr = arr;
  }
  @Override
  public String toString() {
    return "User{" +
        "name='" + name + '\'' +
        ", age=" + age +
        ", arr=" + Arrays.toString(arr) +
        '}';
  }
  public static void main(String[] args) throws IOException, ClassNotFoundException {
    int[] arr = {1,2,3,4,5,6};
    User user = new User("user",22,arr);
 
    ByteArrayOutputStream bo = new ByteArrayOutputStream();
    ObjectOutputStream oo = new ObjectOutputStream(bo);
    oo.writeObject(user);//序列化
    ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
    ObjectInputStream oi = new ObjectInputStream(bi);
    User userClone = (User) oi.readObject();//反序列化
 
    System.out.println("原user:"+user);
    System.out.println("克隆的user:"+userClone);
    user.arr[1] = 9;
    System.out.println("修改后的原user:"+user);
    System.out.println("修改后的克隆user:"+userClone);
  }
}

相關文章

  • Java中static關鍵字的作用和用法詳細介紹

    Java中static關鍵字的作用和用法詳細介紹

    這篇文章主要介紹了Java中static關鍵字的作用和用法詳細介紹,本文講解了static變量、靜態(tài)方法、static代碼塊、static和final一塊用等內(nèi)容,需要的朋友可以參考下
    2015-01-01
  • Java排序算法之SleepSort排序示例

    Java排序算法之SleepSort排序示例

    這篇文章主要介紹了Java排序算法之SleepSort排序,結合實例形式分析了SleepSort排序的實現(xiàn)步驟與相關操作技巧,需要的朋友可以參考下
    2017-01-01
  • Java自動拆箱空指針異常的解決

    Java自動拆箱空指針異常的解決

    這篇文章主要介紹了Java自動拆箱空指針異常的解決,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-03-03
  • SpringBoot+React實現(xiàn)計算個人所得稅

    SpringBoot+React實現(xiàn)計算個人所得稅

    本文將以個人所得稅的計算為例,使用React+SpringBoot+GcExcel來實現(xiàn)這一功能,文中的示例代碼講解詳細,具有一定的學習價值,感興趣的小伙伴可以了解下
    2023-09-09
  • Spring-cloud 服務發(fā)現(xiàn)與消費(以ribbon為例)

    Spring-cloud 服務發(fā)現(xiàn)與消費(以ribbon為例)

    這篇文章主要介紹了Spring-cloud 服務發(fā)現(xiàn)與消費(以ribbon為例),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-04-04
  • J2SE基礎之下載eclipse并創(chuàng)建項目

    J2SE基礎之下載eclipse并創(chuàng)建項目

    本文給大家介紹的是最流行的java 集成開發(fā)環(huán)境IDE eclipse的使用方法,非常的簡單,有需要的小伙伴可以參考下
    2016-05-05
  • 詳解java.lang.reflect.Modifier.isInterface()方法

    詳解java.lang.reflect.Modifier.isInterface()方法

    這篇文章主要介紹了詳解java.lang.reflect.Modifier.isInterface()方法的相關資料,這里提供實例幫助大家理解這個方法的使用,需要的朋友可以參考下
    2017-09-09
  • Spring的@Autowired加到接口上但獲取的是實現(xiàn)類的問題

    Spring的@Autowired加到接口上但獲取的是實現(xiàn)類的問題

    這篇文章主要介紹了Spring的@Autowired加到接口上但獲取的是實現(xiàn)類的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-10-10
  • mybatis查詢語句揭秘之參數(shù)解析

    mybatis查詢語句揭秘之參數(shù)解析

    這篇文章主要給大家介紹了關于mybatis查詢語句之參數(shù)解析的相關資料,文中通過示例代碼介紹的非常詳細,對大家學習或者使用mybatis具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
    2019-04-04
  • Java+MySQL實現(xiàn)圖書管理系統(tǒng)(完整代碼)

    Java+MySQL實現(xiàn)圖書管理系統(tǒng)(完整代碼)

    這篇文章主要介紹了Java+MySQL實現(xiàn)圖書管理系統(tǒng)(完整代碼),本文給大家介紹的非常想詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-01-01

最新評論

昆山市| 兰西县| 和静县| 临澧县| 福建省| 东兰县| 固原市| 佳木斯市| 富源县| 北京市| 伊宁市| 吐鲁番市| 明光市| 明光市| 自治县| 永顺县| 莆田市| 万州区| 三都| 财经| 上思县| 沛县| 万山特区| 富顺县| 西乌珠穆沁旗| 喀什市| 开封县| 合阳县| 莲花县| 南安市| 灵川县| 宝丰县| 寿光市| 郑州市| 德州市| 邵阳县| 武夷山市| 乌兰浩特市| 宿迁市| 登封市| 西乌|