Java中深拷貝和淺拷貝的區(qū)別解析
引用拷貝和對象拷貝
(1)引用拷貝:將對象的引用賦值給引用類型的變量
Object obj = new Object(); Object obj1 = obj;
(2)對象拷貝 創(chuàng)建對象的一個(gè)副本,其中副本和源對象的引用是兩個(gè)不同的地址,而不是把一個(gè)引用賦值給一個(gè)新的引用類型的變量
class Demo{ public static void main(String[] args) throws CloneNotSupportedException { User user = new User(); User user1 = (User)user.clone(); System.out.println(user); System.out.println(user1); } } class User implements Cloneable { @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } }
淺拷貝和深拷貝都是對象拷貝
- 淺拷貝:源對象和拷貝對象的存放地址不同,但被復(fù)制的源對象的引用類型屬性存放的地址仍然和源對象的引用類型屬性相同,修改引用類型屬性的屬性會影響相互影響。
- 深拷貝:源對象和拷貝對象的存放地址不同,源對象和拷貝對象各自的引用類型存放的地址也和源對象的引用類型屬性不同,修改引用類型屬性的屬性不會相互影響拷貝對象和源對象。
常見的淺拷貝方式
(1)一個(gè)引用類型變量直接賦值給另一個(gè)變量
(2)BeaUtil.copyProperties()
常見的深拷貝方式
(1)通過構(gòu)造器或new的方式
(2)重寫繼承至Object方法的clone方法,并實(shí)現(xiàn)Cloneable接口 如果在沒有實(shí)現(xiàn)Cloneable 接口的實(shí)例上調(diào)用 Object 的 clone 方法,則會導(dǎo)致拋出 CloneNotSupportedException 異常,實(shí)現(xiàn)Cloneable 接口的目的是:為了告知JVM,此對象允許拷貝
public class Main { public static void main(String[] args) throws CloneNotSupportedException { User user = new User(1, "測試"); User user1 = user.clone(); System.out.println(user1); } } class User implements Cloneable{ private Integer id; private String name; //必須重寫此方法 @Override protected User clone() throws CloneNotSupportedException { return (User)super.clone(); } public User(Integer id, String name) { this.id = id; this.name = name; } }
注意: 當(dāng)通過Cloneable接口實(shí)現(xiàn)深拷貝時(shí),拷貝的源對象的屬性如果是引用對象(String類型除外),則該屬性也需要實(shí)現(xiàn)Cloneable接口,并覆寫clone方法,否則該屬性是進(jìn)行的淺拷貝。
深拷貝特殊情況(String類型)
String類型屬性:Clonable拷貝后兩個(gè)對象的相同屬性指向了通過字符串,但字符串是不可以修改的,存放在常量池中,當(dāng)其中1個(gè)對象的該屬性指向另個(gè)字符串時(shí),另外一個(gè)對象的屬性的引用仍指向原字符串。
public class ProtoTypeDemo { public static void main(String[] args) throws CloneNotSupportedException { Person person = new Person(); person.setId(1L); person.setName("test"); User user = new User(); user.setUsername("測試"); person.setUser(user); Person person1 = person.clone(); User user1 = user.clone(); user1.setUsername("cs"); person1.setUser(user1); System.out.println(person1);//Person{id=1, name='test', user=User{username='cs'}} System.out.println(person);//Person{id=1, name='test', user=User{username='測試'}} } } public class Person implements Cloneable { private Long id; private String name; private User user; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public Person clone() throws CloneNotSupportedException { return (Person) super.clone(); } public User getUser() { return user; } public void setUser(User user) { this.user = user; } @Override public String toString() { return "Person{" + "id=" + id + ", name='" + name + '\'' + ", user=" + user + '}'; } } public class User implements Cloneable{ private String username; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } @Override public User clone() throws CloneNotSupportedException { return (User) super.clone(); } @Override public String toString() { return "User{" + "username='" + username + '\'' + '}'; } }
(3)序列化的方式:FastJson、Gson等都可以
class Main{ public static void main(String[] args) { User user = new User(1, "測試"); //序列化 String s = JSONObject.toJSONString(user); //反序列化 System.out.println(s); User user1 = JSON.parseObject(s, User.class); System.out.println(user1); } } public class User { private Integer id; private String name; public User(Integer id, String name) { this.id = id; this.name = name; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "User{" + "id=" + id + ", name='" + name + '\'' + '}'; } }
到此這篇關(guān)于Java中深拷貝和淺拷貝的區(qū)別解析的文章就介紹到這了,更多相關(guān)Java深拷貝和淺拷貝內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Mybatis一對多關(guān)聯(lián)關(guān)系映射實(shí)現(xiàn)過程解析
這篇文章主要介紹了Mybatis一對多關(guān)聯(lián)關(guān)系映射實(shí)現(xiàn)過程解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-02-02SpringBoot整合SSO(single sign on)單點(diǎn)登錄
這篇文章主要介紹了SpringBoot整合SSO(single sign on)單點(diǎn)登錄,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06Java easyui樹形表格TreeGrid的實(shí)現(xiàn)代碼
這篇文章主要為大家詳細(xì)介紹了Java easyui樹形表格TreeGrid的實(shí)現(xiàn)代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-03-03詳解spring集成mina實(shí)現(xiàn)服務(wù)端主動(dòng)推送(包含心跳檢測)
本篇文章主要介紹了詳解spring集成mina實(shí)現(xiàn)服務(wù)端主動(dòng)推送(包含心跳檢測),具有一定的參考價(jià)值,與興趣的可以了解一下2017-09-09@PathParam和@QueryParam區(qū)別簡析
這篇文章主要介紹了@PathParam和@QueryParam區(qū)別,分享了相關(guān)實(shí)例代碼,小編覺得還是挺不錯(cuò)的,具有一定借鑒價(jià)值,需要的朋友可以參考下2018-01-01Java中數(shù)組的使用與注意事項(xiàng)詳解(推薦)
數(shù)組是一組地址連續(xù)、長度固定的具有相同類型的數(shù)據(jù)的集合,通過數(shù)組下標(biāo)我們可以指定數(shù)字中的每一個(gè)元素,下面這篇文章主要給大家介紹了關(guān)于Java中數(shù)組的使用與注意事項(xiàng)的相關(guān)資料,需要的朋友可以參考下2021-08-08Java使用agent實(shí)現(xiàn)main方法之前的實(shí)例詳解
這篇文章主要介紹了Java使用agent實(shí)現(xiàn)main方法之前的實(shí)例詳解的相關(guān)資料,希望通過本文能幫助到大家,讓大家理解這部分內(nèi)容,需要的朋友可以參考下2017-10-10