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

Java中深拷貝,淺拷貝與引用拷貝的區(qū)別詳解

 更新時間:2022年08月23日 11:11:54   作者:小牛呼嚕嚕  
這篇文章主要為大家詳細介紹了Java面試中常遇見的問題:深拷貝、淺拷貝與引用拷貝的區(qū)別,文中通過示例進行了詳細講解,需要的可以參考一下

引用拷貝

引用拷貝: 引用拷貝不會在堆上創(chuàng)建一個新的對象,只 會在棧上生成一個新的引用地址,最終指向依然是堆上的同一個對象。

//實體類
public class Person{
    public String name;//姓名
    public int height;//身高
    public StringBuilder something;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public StringBuilder getSomething() {
        return something;
    }

    public void setSomething(StringBuilder something) {
        this.something = something;
    }

    public Person(String name, int height, StringBuilder something) {
        this.name = name;
        this.height = height;
        this.something = something;
    }

}

//測試類
public class copyTest {
    public static void main(String[] args) {
        Person p1 = new Person("小張", 180, new StringBuilder("今天天氣很好"));
        Person p2 = p1;

        System.out.println("對象是否相等:"+ (p1 == p2));
        System.out.println("p1 屬性值=" + p1.getName()+ ","+ p1.getHeight() + ","+ p1.getSomething());
        System.out.println("p2 屬性值=" + p2.getName()+ ","+ p2.getHeight() + ","+ p2.getSomething());


        // change
        p1.name="小王";
        p1.height = 200;
        p1.something.append(",適合出去玩");
        System.out.println("...after p1 change....");

        System.out.println("p1 屬性值=" + p1.getName()+ ","+ p1.getHeight() + ","+ p1.getSomething());
        System.out.println("p2 屬性值=" + p2.getName()+ ","+ p2.getHeight() + ","+ p2.getSomething());

    }
}

結果:

對象是否相等:true
p1 屬性值=小張,180,今天天氣很好
p2 屬性值=小張,180,今天天氣很好
...after p1 change....
p1 屬性值=小王,200,今天天氣很好,適合出去玩
p2 屬性值=小王,200,今天天氣很好,適合出去玩

before change:

after change:

我們可以看出 由于2個引用p1,p2 都是指向堆中同一個對象,所以2個對象是相等的,修改了對象p1,會影響到對象p2
需要注意的

  • name屬性,雖然她是引用類型,但她同時也是String類型,不可變,對其修改,JVM會默認在堆上創(chuàng)建新的內存空間,再重新賦值
  • int weight=180; 是成員變量,存放在堆中,不是所有的基本類型變量 都存放在JVM棧中

注意與這篇文章得區(qū)分開來, int num1 = 10;是基本類型的局部變量,存放在棧中

淺拷貝

淺拷貝 :淺拷貝會在堆上創(chuàng)建一個新的對象,新對象和原對象不等,但是新對象的屬性和老對象相同。

其中:

  • 如果屬性是基本類型(int,double,long,boolean等),拷貝的就是基本類型的值。
  • 如果屬性是引用類型(除了基本類型都是引用類型),拷貝的就是引?數據類型變量的地址值,?對于引?類型變量指向的堆中的對象不會拷貝。

如何實現淺拷貝呢?也很簡單,就是在需要拷貝的類上實現Cloneable接口并重寫其clone()方法

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

在使用的時候直接調用類的clone()方法即可

//實體類 繼承Cloneable
public class Person implements Cloneable{
    public String name;//姓名
    public int height;//身高
    public StringBuilder something;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public StringBuilder getSomething() {
        return something;
    }

    public void setSomething(StringBuilder something) {
        this.something = something;
    }

    public Person(String name, int height, StringBuilder something) {
        this.name = name;
        this.height = height;
        this.something = something;
    }



    @Override
    public Person clone() throws CloneNotSupportedException {
        return (Person) super.clone();
    }

}

//測試類
public class shallowCopyTest {

    public static void main(String[] args) throws CloneNotSupportedException {
        Person p1 = new Person("小張", 180, new StringBuilder("今天天氣很好"));
        Person p2 = p1.clone();

        System.out.println("對象是否相等:"+ (p1 == p2));
        System.out.println("p1 屬性值=" + p1.getName()+ ","+ p1.getHeight() + ","+ p1.getSomething());
        System.out.println("p2 屬性值=" + p2.getName()+ ","+ p2.getHeight() + ","+ p2.getSomething());


        // change
        p1.setName("小王");
        p1.setHeight(200);
        p1.getSomething().append(",適合出去玩");
        System.out.println("...after p1 change....");

        System.out.println("p1 屬性值=" + p1.getName()+ ","+ p1.getHeight() + ","+ p1.getSomething());
        System.out.println("p2 屬性值=" + p2.getName()+ ","+ p2.getHeight() + ","+ p2.getSomething());

    }
}

結果:

對象是否相等:false
p1 屬性值=小張,180,今天天氣很好
p2 屬性值=小張,180,今天天氣很好
...after p1 change....
p1 屬性值=小王,200,今天天氣很好,適合出去玩
p2 屬性值=小張,180,今天天氣很好,適合出去玩

before change:

after change:

我們可以看出:

  • 當我們修改對象p1的weight屬性時,由于p2的height屬性 是直接復制修改前的p1的height屬性,所以還是180。
  • 當我們修改對象p1的name屬性 時,String name指向一個新的內存空間,但對象p2的name還是指向舊的內存空間,所以對象p2的name屬性還是"小張"。
  • 由于對象p1的something屬性和對象p2的something屬性指向是同一個內存空間,當我們修改對象p1的something屬性,會影響到對象p2的something屬性,所以對象p2的something屬性變?yōu)?quot;今天天氣很好,適合出去玩"。

深拷貝

深拷貝 :完全拷貝?個對象,在堆上創(chuàng)建一個新的對象,拷貝被拷貝對象的成員變量的值,同時堆中的對象也會拷貝。
需要重寫clone方法

    @Override
    public Person clone() throws CloneNotSupportedException {
        //return (Person) super.clone();
        Person person = (Person) super.clone();
        person.setSomething( new StringBuilder(person.getSomething()));//單獨為引用類型clone
        return person;
    }

shallowCopyTest測試類的結果:

對象是否相等:false
p1 屬性值=小張,180,今天天氣很好
p2 屬性值=小張,180,今天天氣很好
...after p1 change....
p1 屬性值=小王,200,今天天氣很好,適合出去玩
p2 屬性值=小張,180,今天天氣很好

這時候對象p1和對象p2互不干擾了

before change:

after change:

但這樣也有個小問題,對象每有一個引用類型,我們都得重寫其clone方法,這樣會非常麻煩,因此我們還可以借助序列化來實現對象的深拷貝

//實體類 繼承Cloneable
public class Person implements Serializable{
    public String name;//姓名
    public int height;//身高
    public StringBuilder something;

...//省略 getter setter


    public Object 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 ois.readObject();
    }

}

//測試類,這邊類名筆者就不換了,在之前的基礎上改改
public class shallowCopyTest {

    public static void main(String[] args) throws Exception {
        Person p1 = new Person("小張", 180, new StringBuilder("今天天氣很好"));
        Person p2 = (Person)p1.deepClone();

        System.out.println("對象是否相等:"+ (p1 == p2));
        System.out.println("p1 屬性值=" + p1.getName()+ ","+ p1.getHeight() + ","+ p1.getSomething());
        System.out.println("p2 屬性值=" + p2.getName()+ ","+ p2.getHeight() + ","+ p2.getSomething());


        // change
        p1.setName("小王");
        p1.setHeight(200);
        p1.getSomething().append(",適合出去玩");
        System.out.println("...after p1 change....");

        System.out.println("p1 屬性值=" + p1.getName()+ ","+ p1.getHeight() + ","+ p1.getSomething());
        System.out.println("p2 屬性值=" + p2.getName()+ ","+ p2.getHeight() + ","+ p2.getSomething());

    }
}

這樣也會得到深拷貝的結果

小結

引用拷貝: 引用拷貝不會在堆上創(chuàng)建一個新的對象,只 會在棧上生成一個新的引用地址,最終指向依然是堆上的同一個對象

淺拷貝 :淺拷貝會在堆上創(chuàng)建一個新的對象,新對象和原對象不等,但是新對象的屬性和老對象相同。

其中:

如果屬性是基本類型(int,double,long,boolean等),拷貝的就是基本類型的值。

如果屬性是引用類型(除了基本類型都是引用類型),拷貝的就是引?數據類型變量的地址值,?對于引?類型變量指向的堆中的對象不會拷貝。

深拷貝 :完全拷貝?個對象,在堆上創(chuàng)建一個新的對象,拷貝被拷貝對象的成員變量的值,同時堆中的對象也會拷貝。

以上就是Java中深拷貝,淺拷貝與引用拷貝的區(qū)別詳解的詳細內容,更多關于Java拷貝的資料請關注腳本之家其它相關文章!

相關文章

  • java實現相同屬性名稱及相似類型的pojo、dto、vo等互轉操作

    java實現相同屬性名稱及相似類型的pojo、dto、vo等互轉操作

    這篇文章主要介紹了java實現相同屬性名稱及相似類型的pojo、dto、vo等互轉操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-08-08
  • HashSet如何保證元素不重復(面試必問)

    HashSet如何保證元素不重復(面試必問)

    HashSet 不保證集合的迭代順序,但允許插入 null 值,也就是說它可以將集合中的重復元素自動過濾掉,保證存儲在 HashSet 中的元素都是唯一的,這篇文章主要介紹了HashSet如何保證元素不重復(面試必問),需要的朋友可以參考下
    2021-12-12
  • SpringBoot中RestTemplate的使用詳解

    SpringBoot中RestTemplate的使用詳解

    這篇文章主要介紹了SpringBoot中RestTemplate的使用詳解,RestTemplate是由Spring框架提供的一個可用于應用中調用rest服務的類它簡化了與http服務的通信方式,統(tǒng)一了RESTFul的標準,封裝了http連接,我們只需要傳入url及其返回值類型即可,需要的朋友可以參考下
    2023-10-10
  • java中使用zxing批量生成二維碼立牌

    java中使用zxing批量生成二維碼立牌

    本篇文章主要介紹了java中使用zxing批量生成二維碼立牌,非常具有實用價值,需要的朋友可以參考下。
    2016-12-12
  • MybatisPlus3.5.5與pagehelper?starter2.1.0沖突的問題解決

    MybatisPlus3.5.5與pagehelper?starter2.1.0沖突的問題解決

    在使用MybatisPlus?3.5.5與PageHelper?Starter?2.1.0時,由于引用了不同版本的jsqlparser庫(4.6與4.7),會導致運行時錯誤,解決方案涉及確認依賴版本,本文就來介紹一下,感興趣的同學可以下載學習
    2024-10-10
  • springboot整合vue實現上傳下載文件

    springboot整合vue實現上傳下載文件

    這篇文章主要為大家詳細介紹了springboot整合vue實現上傳下載文件,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-11-11
  • 詳解Java之路(五) 訪問權限控制

    詳解Java之路(五) 訪問權限控制

    本篇文章主要介紹了Java之路(五) 訪問權限控制 ,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。
    2016-12-12
  • Springboot中的Controller解析

    Springboot中的Controller解析

    這篇文章主要介紹了Springboot中的Controller解析,Controller是SpringBoot的基本組件,也是MVC結構的組成部分,其作用是將用戶提交來的請求通過URL匹配,分發(fā)給不同的接收器,該接收器會對其進行相應處理,然后返回處理結果,需要的朋友可以參考下
    2023-09-09
  • mybatis-parameterType傳入map條件方式

    mybatis-parameterType傳入map條件方式

    這篇文章主要介紹了mybatis-parameterType傳入map條件方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • GC參考手冊二java中垃圾回收原理解析

    GC參考手冊二java中垃圾回收原理解析

    由于有個垃圾回收機制,java中的額對象不在有“作用域”的概念,只有對象的引用才有“作用域”。垃圾回收可以有效的防止內存泄露,有效的使用空閑的內存<BR>
    2022-01-01

最新評論

镇沅| 谷城县| 石嘴山市| 新余市| 融水| 吴川市| 沂南县| 奉节县| 宿州市| 新巴尔虎左旗| 正安县| 应用必备| 武穴市| 昌乐县| 萍乡市| 乌兰县| 乐业县| 嘉禾县| 青田县| 普格县| 灵丘县| 广昌县| 桂林市| 巴林左旗| 湟中县| 宁陕县| 新安县| 错那县| 嘉善县| 铁力市| 同仁县| 禄劝| 闻喜县| 宁城县| 孟村| 桦甸市| 汤原县| 兰坪| 孟连| 泌阳县| 石阡县|