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

實(shí)例分析java對(duì)象中淺克隆和深克隆

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

引言:

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

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

Object類(lèi)中的clone方法是protected修飾的,這就表明我們?cè)谧宇?lèi)中不重寫(xiě)此方法,就在子類(lèi)外無(wú)法訪問(wèn),因?yàn)檫@個(gè)protected權(quán)限是僅僅能在Object所在的包和子類(lèi)能訪問(wèn)的,這也驗(yàn)證了子類(lèi)重寫(xiě)父類(lèi)方法權(quán)限修飾符可以變大但不能變小的說(shuō)法。

protected native Object clone() throws CloneNotSupportedException;

重寫(xiě)clone方法,內(nèi)部?jī)H僅是調(diào)用了父類(lèi)的clone方法,其實(shí)是為了擴(kuò)大訪問(wèn)權(quán)限,當(dāng)然你可以把protected改為public,以后再繼承就不用重寫(xiě)了。當(dāng)然只是淺克隆的clone函數(shù),深克隆就需要修改了。

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

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

淺克隆:

淺克隆就是引用類(lèi)型的屬性無(wú)法完全復(fù)制,類(lèi)User中包含成績(jī)屬性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);
    //修改引用類(lèi)型的mark屬性
    user.mark.setMath(60);
    System.out.println("修改后的原user:"+user);
    System.out.println("修改后的克隆user:"+userClone);
  }
}

輸出結(jié)果為:   

原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)用

既然引用類(lèi)型無(wú)法被完全克隆,那將引用類(lèi)型也實(shí)現(xiàn)Cloneable接口重寫(xiě)clone方法,在User類(lèi)中的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);
    //修改引用類(lèi)型的mark屬性
    user.mark.setMath(60);
    System.out.println("修改后的原user:"+user);
    System.out.println("修改后的克隆user:"+userClone);
  }
}

輸出結(jié)果為: 

原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)足夠滿足我們的需要,但是如果類(lèi)之間的關(guān)系很多,或者是有的屬性是數(shù)組呢,數(shù)組可無(wú)法實(shí)現(xiàn)Cloneable接口(我們可以在clone方法中手動(dòng)復(fù)制數(shù)組),但是每次都得手寫(xiě)clone方法,很麻煩,而序列化方式只需要給每個(gè)類(lèi)都實(shí)現(xiàn)一個(gè)Serializable接口,也是標(biāo)記接口,最后同序列化和反序列化操作達(dá)到克隆的目的(包括數(shù)組的復(fù)制)。序列化和反序列化的知識(shí)請(qǐng)參照下一篇

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);
  }
}

輸出結(jié)果:

原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);
  }
}

相關(guān)文章

  • Java中static關(guān)鍵字的作用和用法詳細(xì)介紹

    Java中static關(guān)鍵字的作用和用法詳細(xì)介紹

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

    Java排序算法之SleepSort排序示例

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

    Java自動(dòng)拆箱空指針異常的解決

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

    SpringBoot+React實(shí)現(xiàn)計(jì)算個(gè)人所得稅

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

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

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

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

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

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

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

    Spring的@Autowired加到接口上但獲取的是實(shí)現(xiàn)類(lèi)的問(wèn)題

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

    mybatis查詢(xún)語(yǔ)句揭秘之參數(shù)解析

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

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

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

最新評(píng)論

麻江县| 吉林省| 芷江| 双城市| 宝山区| 嫩江县| 伊金霍洛旗| 鱼台县| 井冈山市| 德州市| 梁山县| 河东区| 科尔| 吉首市| 左云县| 建始县| 新绛县| 峡江县| 石楼县| 山阳县| 灌云县| 探索| 内黄县| 腾冲县| 河源市| 阿拉尔市| 宜丰县| 类乌齐县| 湘阴县| 祁阳县| 平利县| 余江县| 泾源县| 吉木乃县| 威远县| 乐山市| 沐川县| 昭觉县| 壤塘县| 宁南县| 浪卡子县|