欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java中淺拷貝和深拷貝詳解

 更新時(shí)間:2021年12月06日 16:25:14   作者:Ccy丶雙  
大家好,本篇文章主要講的是Java中淺拷貝和深拷貝詳解,感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下,方便下次瀏覽

Java淺拷貝深拷貝

淺拷貝和深拷貝涉及到了Object類中的clone()方法

在這里插入圖片描述

實(shí)現(xiàn)淺拷貝

淺拷貝的實(shí)現(xiàn)需要類重寫clone()方法

淺拷貝會(huì)創(chuàng)建一個(gè)新對象,這個(gè)對象有著原始對象屬性值的一份精確拷貝

如果屬性是基本類型,拷貝的就是基本類型的值;

如果屬性是內(nèi)存地址(引用類型),拷貝的就是內(nèi)存地址 ,因此如果其中一個(gè)對象改變了這個(gè)地址,就會(huì)影響到另一個(gè)對象,導(dǎo)致兩個(gè)對象的引用不等。

實(shí)現(xiàn)淺拷貝很簡單只需要將類實(shí)現(xiàn)Cloneable接口然后重寫clone方法即可

class Person implements Cloneable {
    String name;
    int age;

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

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

    /**
         * 重寫clone()方法
         *
         * @return
         * @throws CloneNotSupportedException
         */
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    @Override
    public String toString() {
        return "Person{" +
            "name='" + name + '\'' +
            ", age=" + age +
            '}';
    }
}

測試淺拷貝特性

public void testClone() throws CloneNotSupportedException {
    Person person1 = new Person();
    person1.setName("ccy");
    person1.setAge(20);
    Person person2 = (Person) person1.clone();
    //查看淺拷貝效果
    System.out.println(person1);
    System.out.println(person2);
    System.out.println(person1.getName() == person2.getName());
    //驗(yàn)證clone()的特性
    System.out.println(person1.clone() != person1);
    System.out.println(person1.clone().getClass() == person1.getClass());
    //如果是基本類型淺拷貝直接賦值值,如果是引用類型淺拷貝指向其內(nèi)存地址即共享內(nèi)存地址
    //改變person1的引用類型String屬性的值,引用發(fā)生改變
    person1.setName("zfs");
    System.out.println(person2.getName());
}

在這里插入圖片描述

實(shí)現(xiàn)深拷貝

對于上述的問題雖然拷貝的兩個(gè)對象不同,但其內(nèi)部的一些引用還是相同的,怎么樣絕對的拷貝這個(gè)對象,使這個(gè)對象完全獨(dú)立于原對象呢?就使用我們的深拷貝了。深拷貝:在對引用數(shù)據(jù)類型進(jìn)行拷貝的時(shí)候,創(chuàng)建了一個(gè)新的對象,并且復(fù)制其內(nèi)的成員變量。

在具體實(shí)現(xiàn)深拷貝上,這里提供兩個(gè)方式,重寫clone()方法和序列法。

重寫clone()方法

如果使用重寫clone()方法實(shí)現(xiàn)深拷貝,那么要將類中所有自定義引用變量的類也去實(shí)現(xiàn)Cloneable接口實(shí)現(xiàn)clone()方法。對于字符類可以創(chuàng)建一個(gè)新的字符串實(shí)現(xiàn)拷貝。但是對于自定義類需要實(shí)現(xiàn)cloneable重寫clone,這樣做就太麻煩了所以我們使用序列化

序列化

序列化后將二進(jìn)制字節(jié)流內(nèi)容寫到一個(gè)媒介(文本或字節(jié)數(shù)組),然后是從這個(gè)媒介讀取數(shù)據(jù),原對象寫入這個(gè)媒介后拷貝給clone對象,原對象的修改不會(huì)影響clone對象,因?yàn)閏lone對象是從這個(gè)媒介讀取。

熟悉對象緩存的知道我們經(jīng)常將Java對象緩存到Redis中,然后還可能從Redis中讀取生成Java對象,這就用到序列化和反序列化。一般可以將Java對象存儲(chǔ)為字節(jié)流或者json串然后反序列化成Java對象。因?yàn)樾蛄谢瘯?huì)儲(chǔ)存對象的屬性但是不會(huì)也無法存儲(chǔ)對象在內(nèi)存中地址相關(guān)信息。所以在反序列化成Java對象時(shí)候會(huì)重新創(chuàng)建所有的引用對象。

在具體實(shí)現(xiàn)上,自定義的類需要實(shí)現(xiàn)Serializable接口

class Person implements Serializable {
    String name;
    int age;

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

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

    @Override
    public String toString() {
        return "Person{" +
            "name='" + name + '\'' +
            ", age=" + age +
            '}';
    }

    protected Person deepClone() throws Exception {
        //序列化
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);

        oos.writeObject(this);

        //反序列化
        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bis);

        return (Person) ois.readObject();
    }
}

測試方法

public void testClone() throws Exception {
    Person person1 = new Person();
    person1.setName("ccy");
    person1.setAge(20);
    Person person2 = person1.deepClone();
    System.out.println(person1.getName() == person2.getName());
}

在這里插入圖片描述

可以看到兩個(gè)引用對象的地址并不同,成功實(shí)現(xiàn)了深拷貝

到此這篇關(guān)于Java中淺拷貝和深拷貝詳解的文章就介紹到這了,更多相關(guān)Java淺拷貝深拷貝內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot2.7.14整合redis7的詳細(xì)過程

    SpringBoot2.7.14整合redis7的詳細(xì)過程

    這篇文章主要介紹了SpringBoot2.7.14整合redis7的詳細(xì)過程,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2023-10-10
  • Java實(shí)現(xiàn)簡易版聯(lián)網(wǎng)坦克對戰(zhàn)小游戲(附源碼)

    Java實(shí)現(xiàn)簡易版聯(lián)網(wǎng)坦克對戰(zhàn)小游戲(附源碼)

    這篇文章主要給大家介紹了關(guān)于Java實(shí)現(xiàn)簡易版聯(lián)網(wǎng)坦克對戰(zhàn)小游戲的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用java具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • Java動(dòng)態(tài)規(guī)劃篇之線性DP的示例詳解

    Java動(dòng)態(tài)規(guī)劃篇之線性DP的示例詳解

    這篇文章主要通過幾個(gè)例題為大家詳細(xì)介紹一些Java動(dòng)態(tài)規(guī)劃中的線性DP,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)Java有一定的幫助,需要的可以參考一下
    2022-11-11
  • 5分鐘快速學(xué)會(huì)spring boot整合Mybatis的方法

    5分鐘快速學(xué)會(huì)spring boot整合Mybatis的方法

    這篇文章主要給大家介紹了如何通過5分鐘快速學(xué)會(huì)spring boot整合Mybatis的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用spring boot具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12
  • Java AQS中CyclicBarrier回環(huán)柵欄的使用

    Java AQS中CyclicBarrier回環(huán)柵欄的使用

    這篇文章主要介紹了Java中的 CyclicBarrier詳解,CyclicBarrier沒有顯示繼承哪個(gè)父類或者實(shí)現(xiàn)哪個(gè)父接口, 所有AQS和重入鎖不是通過繼承實(shí)現(xiàn)的,而是通過組合實(shí)現(xiàn)的,下文相關(guān)內(nèi)容需要的小伙伴可以參考一下
    2023-02-02
  • 淺談shiro的SecurityManager類結(jié)構(gòu)

    淺談shiro的SecurityManager類結(jié)構(gòu)

    下面小編就為大家?guī)硪黄獪\談shiro的SecurityManager類結(jié)構(gòu)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-07-07
  • netty中pipeline的handler添加刪除分析

    netty中pipeline的handler添加刪除分析

    這篇文章主要為大家介紹了netty中pipeline的handler添加刪除分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-04-04
  • SpringBoot集成RocketMQ的使用示例

    SpringBoot集成RocketMQ的使用示例

    RocketMQ是阿里巴巴開源的一款消息中間件,性能優(yōu)秀,功能齊全,被廣泛應(yīng)用在各種業(yè)務(wù)場景,本文就來介紹一下SpringBoot集成RocketMQ的使用示例,感興趣的可以了解一下
    2023-11-11
  • 如何更快樂的使用Java 8中的Lambda特性

    如何更快樂的使用Java 8中的Lambda特性

    從java8出現(xiàn)以來lambda是最重要的特性之一,它可以讓我們用簡潔流暢的代碼完成一個(gè)功能。下面這篇文章主要給大家介紹了關(guān)于如何更快樂的使用Java 8中的Lambda特性的相關(guān)資料,需要的朋友可以參考下
    2018-11-11
  • Java實(shí)現(xiàn)生成JSON字符串的三種方式分享

    Java實(shí)現(xiàn)生成JSON字符串的三種方式分享

    這篇文章主要來和大家分享一下Java實(shí)現(xiàn)生成JSON字符串的常見三種方式,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價(jià)值,需要的可以參考一下
    2023-05-05

最新評(píng)論