日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當前位置:首頁 > 科技  > 軟件

深入理解Java淺拷貝與深拷貝

來源: 責編: 時間:2024-03-18 09:39:35 233觀看
導讀淺拷貝和深拷貝是 Java 初中級面試中經常會被問到的一個問題,兩個就像是兄弟倆,一個調皮一個乖巧,現在讓我們一起來探索它們的奇妙之處!特別說明:不論是淺拷貝還是深拷貝,都可以使用Object類的clone方法來實現,代碼如下:prote

淺拷貝和深拷貝是 Java 初中級面試中經常會被問到的一個問題,兩個就像是兄弟倆,一個調皮一個乖巧,現在讓我們一起來探索它們的奇妙之處!2zh28資訊網——每日最新資訊28at.com

特別說明:不論是淺拷貝還是深拷貝,都可以使用Object類的clone方法來實現,代碼如下:2zh28資訊網——每日最新資訊28at.com

protected native Object clone() throws CloneNotSupportedException;

注意:clone()方法也是一個本地方法,具體實現交給虛擬機,也就是說虛擬機在運行給方法時,就會變成搞笑的C/C++代碼。2zh28資訊網——每日最新資訊28at.com

1. 淺拷貝

先讓我們來了解一下淺拷貝。它就像是我們上學時抄了學霸一份作業,但結果可能讓人出乎意料。為了演示這一點,我們創建了一個名為Student的類,這個學生有一個名為“name”的字符串字段和一個名為“age”的整數字段。2zh28資訊網——每日最新資訊28at.com

public class Student implements  Cloneable{    private int age;    private String name;    public Student(int age, String name) {        this.age = age;        this.name = name;    }    public int getAge() {        return age;    }    public void setAge(int age) {        this.age = age;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    @Override    public String toString() {        return super.toString().substring(19) + "{" +                "age=" + age +                ", name='" + name + '/'' +                '}';    }    @Override    public   Object clone() throws CloneNotSupportedException {        return super.clone();    }}

接著,我們來進行測試。假設我們有一個名叫“springboot葵花寶典”的Student對象,并進行了淺拷貝。結果出來了!讓我們看看會發生什么。2zh28資訊網——每日最新資訊28at.com

public class CloneTest {    public static void main(String[] args) throws CloneNotSupportedException {        Student student1 = new Student(18,"springboot葵花寶典");        Student student2 = (Student) student1.clone();        System.out.println("淺拷貝后:");        System.out.println("Student1:" + student1);        System.out.println("Student2:" + student2);        student2.setName("zbbmeta");        System.out.println("調整了Student2 的 name  后:");        System.out.println("Student1:" + student1);        System.out.println("Student2:" + student2);    }}

測試結果如下:2zh28資訊網——每日最新資訊28at.com

淺拷貝后:Student1:Student@4cb2c100{age=18, name='springboot葵花寶典'}Student2:Student@39fb3ab6{age=18, name='springboot葵花寶典'}調整了Student2 的 name  后:Student1:Student@4cb2c100{age=18, name='springboot葵花寶典'}Student2:Student@39fb3ab6{age=18, name='zbbmeta'}

淺拷貝后,Student1 和 Student1 引用不同對象,但值是相同的,說明拷貝成功。之后,修改了 Student2 的 name 字段,student2的name和student1的name值不同。2zh28資訊網——每日最新資訊28at.com

2zh28資訊網——每日最新資訊28at.com

圖片圖片2zh28資訊網——每日最新資訊28at.com

注意:一個類沒有實現 Cloneable 接口,即便它重寫了 clone() 方法,依然是無法調用該方法進行對象克隆的,會拋出異常CloneNotSupportedException。2zh28資訊網——每日最新資訊28at.com

Exception in thread "main" java.lang.CloneNotSupportedException: com.zbbmeta.entity.Student

2zh28資訊網——每日最新資訊28at.com

思考:前面Student只有兩個基本類型,沒有引用類型,如果給Student添加一個自定義Book引用類型,淺拷貝會是什么結果?2zh28資訊網——每日最新資訊28at.com

public class Book {    private String bookName;    private int price;    public Book(String bookName, int price) {        this.bookName = bookName;        this.price = price;    }    //...   省略getter/setter 方法      @Override    public String toString() {        return super.toString().substring(19) +                " bookName='" + bookName + '/'' +                ", price=" + price +                '}';    }}

重新編寫Studnet類:2zh28資訊網——每日最新資訊28at.com

public class Student implements  Cloneable{    private int age;    private String name;    private Book book;    public Student(int age, String name, Book book) {        this.age = age;        this.name = name;        this.book = book;    }   //...   省略getter/setter 方法    @Override    public String toString() {        return super.toString().substring(19) +                " age=" + age +                ", name='" + name + '/'' +                ", book=" + book +                '}';    }    @Override    public   Object clone() throws CloneNotSupportedException {        return super.clone();    }}

比之前的例子多了一個自定義類型的字段 book,clone() 方法并沒有任何改變。2zh28資訊網——每日最新資訊28at.com

測試類修改內容如下:2zh28資訊網——每日最新資訊28at.com

public static void main(String[] args) throws CloneNotSupportedException {        Student student1 = new Student(18,"springboot葵花寶典");        Book book1 = new Book("springboot入門到精通",90);        student1.setBook(book1);        Student student2 = (Student) student1.clone();        System.out.println("淺拷貝后:");        System.out.println("Student1:" + student1);        System.out.println("Student2:" + student2);        Book book2 = student2.getBook();        book2.setBookName("K8S實戰");        book2.setPrice(70);        System.out.println("調整了Student2 的 book  后:");        System.out.println("Student1:" + student1);        System.out.println("Student2:" + student2);    }

輸出結果如下:2zh28資訊網——每日最新資訊28at.com

淺拷貝后:Student1:Student@6fb554cc age=18, name='springboot葵花寶典', book=Book@3c09711b bookName='springboot入門到精通', price=90}}Student2:Student@3a82f6ef age=18, name='springboot葵花寶典', book=Book@3c09711b bookName='springboot入門到精通', price=90}}調整了Student2 的 book  后:Student1:Student@6fb554cc age=18, name='springboot葵花寶典', book=Book@3c09711b bookName='K8S實戰', price=70}}Student2:Student@3a82f6ef age=18, name='springboot葵花寶典', book=Book@3c09711b bookName='K8S實戰', price=70}}

student2.book 變更后,student1.book 也發生了改變。這是因為name字符串 String 是不可變對象,一個新的值必須在字符串常量池中開辟一段新的內存空間,而Book是自定義對象的內存地址并沒有發生改變,只是對應的字段值發生了改變。2zh28資訊網——每日最新資訊28at.com

2zh28資訊網——每日最新資訊28at.com

2zh28資訊網——每日最新資訊28at.com

總結:淺拷貝是創建一個新的對象,這個對象有著對原始對象屬性值的一份精確拷貝。如果屬性是基本數據類型,拷貝的就是基本數據類型的值;如果屬性是引用數據類型,拷貝的就是內存地址,所以如果其中一個對象改變了引用類型的數據,就會影響另一個對象。2zh28資訊網——每日最新資訊28at.com

2. 深拷貝

深拷貝和淺拷貝不同的,深拷貝中的引用類型字段也會克隆一份,當改變任何一個對象,另外一個對象不會隨之改變。例子如下:2zh28資訊網——每日最新資訊28at.com

public class Book implements Cloneable{    private String bookName;    private int price;    public Book(String bookName, int price) {        this.bookName = bookName;        this.price = price;    } //...   省略getter/setter 方法    @Override    public String toString() {        return super.toString().substring(19) +                " bookName='" + bookName + '/'' +                ", price=" + price +                '}';    }    @Override    public Object clone() throws CloneNotSupportedException {        return super.clone();    }}

注意:此時的 Book 類和淺拷貝時不同,重寫了 clone() 方法,并實現了 Cloneable 接口。為的就是深拷貝的時候也能夠克隆該字段。2zh28資訊網——每日最新資訊28at.com

重新編寫Studnet類:2zh28資訊網——每日最新資訊28at.com

public class Student implements  Cloneable{    private int age;    private String name;    private Book book;    public Student(int age, String name, Book book) {        this.age = age;        this.name = name;        this.book = book;    }   //...   省略getter/setter 方法    @Override    public String toString() {        return super.toString().substring(19) +                " age=" + age +                ", name='" + name + '/'' +                ", book=" + book +                '}';    }    @Override    public Object clone() throws CloneNotSupportedException {        Student student = (Student) super.clone();        student.setBook((Book) student.getBook().clone());        return student;    }}

注意,此時 Student 類也與之前的不同,clone() 方法當中,不再只調用 Object 的 clone() 方法對 Student 進行克隆了,還對 Book 也進行了克隆。2zh28資訊網——每日最新資訊28at.com

測試結果如下:2zh28資訊網——每日最新資訊28at.com

淺拷貝后:Student1:Student@6fb554cc age=18, name='springboot葵花寶典', book=Book@3c09711b bookName='springboot入門到精通', price=90}}Student2:Student@3a82f6ef age=18, name='springboot葵花寶典', book=Book@100fc185 bookName='springboot入門到精通', price=90}}調整了Student2 的 book  后:Student1:Student@6fb554cc age=18, name='springboot葵花寶典', book=Book@3c09711b bookName='springboot入門到精通', price=90}}Student2:Student@3a82f6ef age=18, name='springboot葵花寶典', book=Book@100fc185 bookName='K8S實戰', price=70}}

發現: 不僅student1 和 student2 對象不同,它們中的 book 對象不同。所以,改變了 student2 中的 book 并不會影響到 student1。2zh28資訊網——每日最新資訊28at.com

2zh28資訊網——每日最新資訊28at.com

圖片圖片2zh28資訊網——每日最新資訊28at.com

思考:嵌套的對象比較多的時,每一個類都需要重寫clone()方法,這樣拷貝起來就比較麻煩,那么有沒有別的方法實現深拷貝。2zh28資訊網——每日最新資訊28at.com

利用序列化,序列化是將對象寫到流中便于傳輸,而反序列化則是將對象從流中讀取出來。寫入流中的對象就是對原始對象的拷貝。需要注意的是,每個要序列化的類都要實現 Serializable 接口,該接口和 Cloneable 接口類似,都是標記型接口。2zh28資訊網——每日最新資訊28at.com

public class Book implements Cloneable{    private String bookName;    private int price;    public Book(String bookName, int price) {        this.bookName = bookName;        this.price = price;    } //...   省略getter/setter 方法    @Override    public String toString() {        return super.toString().substring(19) +                " bookName='" + bookName + '/'' +                ", price=" + price +                '}';    }}

注意:Book 需要實現 Serializable 接口。2zh28資訊網——每日最新資訊28at.com

重新編寫Studnet類:2zh28資訊網——每日最新資訊28at.com

public class Student implements  Cloneable{    private int age;    private String name;    private Book book;    public Student(int age, String name, Book book) {        this.age = age;        this.name = name;        this.book = book;    }   //...   省略getter/setter 方法    @Override    public String toString() {        return super.toString().substring(19) +                " age=" + age +                ", name='" + name + '/'' +                ", book=" + book +                '}';    }    //深度拷貝    public Object deepClone() throws IOException, ClassNotFoundException {        // 序列化        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();    }}

注意:Student 類實現 Serializable 接口,并且在該類中,增加了一個 deepClone() 的方法,利用 OutputStream 進行序列化,InputStream 進行反序列化,這樣就實現了深拷貝。2zh28資訊網——每日最新資訊28at.com

public static void main(String[] args) throws  IOException, ClassNotFoundException {        Student student1 = new Student(18,"springboot葵花寶典");        Book book1 = new Book("springboot入門到精通",90);        student1.setBook(book1);        Student student2 = (Student) student1.deepClone();        System.out.println("淺拷貝后:");        System.out.println("Student1:" + student1);        System.out.println("Student2:" + student2);        Book book2 = student2.getBook();        book2.setBookName("K8S實戰");        book2.setPrice(70);        System.out.println("調整了Student2 的 book  后:");        System.out.println("Student1:" + student1);        System.out.println("Student2:" + student2);    }

與之前測試類不同的是,調用了 deepClone() 方法。2zh28資訊網——每日最新資訊28at.com

測試結果如下:2zh28資訊網——每日最新資訊28at.com

淺拷貝后:Student1:Student@5dfcfece age=18, name='springboot葵花寶典', book=Book@5d5eef3d bookName='springboot入門到精通', price=90}}Student2:Student@5a8e6209 age=18, name='springboot葵花寶典', book=Book@4b4523f8 bookName='springboot入門到精通', price=90}}調整了Student2 的 book  后:Student1:Student@5dfcfece age=18, name='springboot葵花寶典', book=Book@5d5eef3d bookName='springboot入門到精通', price=90}}Student2:Student@5a8e6209 age=18, name='springboot葵花寶典', book=Book@4b4523f8 bookName='K8S實戰', price=70}}

測試結果和之前用 clone() 方法實現的深拷貝類似。2zh28資訊網——每日最新資訊28at.com

特別說明:序列化涉及到輸入流和輸出流的讀寫,在性能上要比  虛擬機實現的 clone() 方法差很多。2zh28資訊網——每日最新資訊28at.com

本文鏈接:http://m.www897cc.com/showinfo-26-76500-0.html深入理解Java淺拷貝與深拷貝

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: Synchronized關鍵字的底層原理?

下一篇: VR在工業培訓中的興起,讓明天更安全

標簽:
  • 熱門焦點
Top 日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不
欧美三级不卡| 亚洲午夜激情在线| 麻豆精品精华液| 久久久久久久尹人综合网亚洲| 亚洲一区免费看| 亚洲一区二区三区视频| 亚洲欧洲99久久| 亚洲社区在线观看| 午夜精品电影| 午夜欧美精品久久久久久久| 久久久午夜精品| 久久夜色精品亚洲噜噜国产mv| 久久躁日日躁aaaaxxxx| 老巨人导航500精品| 欧美岛国激情| 国产精品久久97| 国产精品乱人伦中文| 国产欧美日韩精品a在线观看| 国产精品国码视频| 国产亚洲成精品久久| 国产在线播精品第三| 在线电影欧美日韩一区二区私密| 亚洲高清在线| 99精品国产热久久91蜜凸| 一区二区不卡在线视频 午夜欧美不卡在 | 亚洲激情影院| 日韩亚洲综合在线| 亚洲一区二区欧美| 久久国产免费| 欧美成人一区二区| 国产精品久线观看视频| 国产欧美短视频| 狠狠色狠狠色综合日日五| 亚洲三级免费观看| 性高湖久久久久久久久| 欧美二区在线| 欧美视频一区二| 亚洲高清不卡| 这里是久久伊人| 美女爽到呻吟久久久久| 欧美无砖砖区免费| 激情久久五月天| 一区二区国产在线观看| 久久av老司机精品网站导航| 欧美日韩美女在线观看| 在线播放亚洲一区| 一区二区91| 欧美大片国产精品| 国产欧美精品在线播放| 妖精视频成人观看www| 久久中文字幕导航| 国产精品成人在线观看| 亚洲国产精品va在线看黑人动漫| 亚洲免费在线观看视频| 欧美日本中文字幕| 黄色成人在线| 亚洲自拍偷拍福利| 欧美日韩国内自拍| 亚洲经典视频在线观看| 欧美在线观看日本一区| 欧美三级第一页| 亚洲人午夜精品免费| 久久天天躁夜夜躁狠狠躁2022 | 亚洲一区二区在线免费观看| 欧美精品999| 亚洲国产精品久久| 久久一二三区| 国内精品一区二区三区| 欧美一级一区| 国产精品一区久久久久| 亚洲一区视频在线观看视频| 欧美日韩mv| 日韩视频精品| 欧美精品激情blacked18| 亚洲国产小视频| 久久综合999| 在线精品国产欧美| 久久亚洲精品一区| 激情婷婷亚洲| 久久久久青草大香线综合精品| 国产精品美女视频网站| 亚洲一区免费视频| 欧美性色aⅴ视频一区日韩精品| 99精品视频免费| 欧美日韩国产色站一区二区三区| 亚洲精品欧美日韩专区| 欧美激情在线狂野欧美精品| 亚洲黄色成人网| 欧美国产在线视频| 亚洲精品一区在线观看| 欧美激情精品久久久久久变态| 亚洲娇小video精品| 欧美国产国产综合| 亚洲毛片在线免费观看| 欧美日韩久久不卡| 亚洲视频999| 一区二区三区欧美| 欧美日本网站| 亚洲视频综合| 国产乱码精品| 久久国产精品一区二区三区| 国产日韩精品在线观看| 香蕉久久a毛片| 国产一区在线看| 老司机午夜免费精品视频 | 亚洲性线免费观看视频成熟| 国产精品久久夜| 欧美在线地址| 在线观看亚洲专区| 欧美激情亚洲激情| 中文日韩在线| 国产日韩欧美亚洲| 久久视频在线视频| 亚洲国产另类 国产精品国产免费| 欧美高清不卡在线| 一区二区动漫| 国产欧美日韩在线观看| 久久久视频精品| 亚洲精品在线观看视频| 欧美日韩一级黄| 欧美在线二区| 91久久精品日日躁夜夜躁欧美| 欧美日韩精品综合| 欧美亚洲一级| 亚洲国内精品在线| 欧美亚一区二区| 久久国产99| 亚洲精选91| 国产欧美精品日韩| 免费视频久久| 亚洲在线不卡| 尤物yw午夜国产精品视频明星| 欧美精品激情在线| 欧美一区91| 亚洲人成在线播放网站岛国| 国产精品久久综合| 美女视频网站黄色亚洲| 亚洲小说春色综合另类电影| 国内揄拍国内精品久久| 欧美日韩精品福利| 久久精彩视频| 一本色道久久88精品综合| 国产亚洲欧洲一区高清在线观看| 欧美国产大片| 欧美一区二区三区啪啪| 最新日韩欧美| 国产伦理一区| 欧美激情第二页| 欧美在线一区二区三区| 日韩视频在线一区| 韩国精品久久久999| 欧美三级电影精品| 免播放器亚洲| 午夜亚洲性色福利视频| 亚洲精品美女在线| 国产在线一区二区三区四区 | 欧美视频手机在线| 麻豆精品视频在线| 午夜精品久久久久久久男人的天堂 | 一区二区三区你懂的| 国内精品一区二区| 国产精品久久毛片a| 欧美激情a∨在线视频播放| 欧美中文字幕在线| 亚洲视频1区| 亚洲人成在线播放网站岛国| 国产亚洲毛片在线| 欧美性开放视频| 欧美91福利在线观看| 午夜精品久久久久久久男人的天堂| 亚洲精品久久嫩草网站秘色| 国产日韩欧美一区在线| 欧美日韩亚洲国产一区| 美乳少妇欧美精品| 久久精品国产亚洲a| 亚洲午夜精品一区二区| 亚洲精品少妇30p| 在线电影国产精品| 国模吧视频一区| 国产精品网站在线| 欧美亚洲不卡| 欧美日韩亚洲一区二| 欧美激情视频一区二区三区不卡| 久久视频在线视频| 久久精品成人欧美大片古装| 亚洲欧美日韩在线综合| 中文有码久久| 99国产精品久久久| 亚洲精品国产精品久久清纯直播| 在线观看成人一级片| 好吊日精品视频| 国产一区二区三区视频在线观看| 国产精品欧美在线| 国产精品护士白丝一区av| 欧美三级日韩三级国产三级| 欧美区在线观看| 欧美精品在线极品| 欧美激情亚洲自拍| 欧美福利影院| 欧美激情 亚洲a∨综合| 欧美国产视频在线观看| 欧美激情精品久久久久久大尺度| 欧美岛国激情| 欧美日本韩国一区二区三区|