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

