Java對(duì)象深復(fù)制與淺復(fù)制實(shí)例詳解
Java對(duì)象深復(fù)制與淺復(fù)制實(shí)例詳解
我們?cè)谟龅揭恍I(yè)務(wù)場(chǎng)景的時(shí)候經(jīng)常需要對(duì)對(duì)象進(jìn)行復(fù)制,對(duì)于對(duì)象的復(fù)制一般有兩種方式,深復(fù)制和淺復(fù)制
淺復(fù)制:對(duì)象的復(fù)制僅是對(duì)象本身,對(duì)象引用的其它對(duì)方并不會(huì)復(fù)制。
深復(fù)制:對(duì)象的復(fù)制包含對(duì)象引用的對(duì)象。
Java所有對(duì)象的基類(lèi)提供了clone方法,但是這個(gè)方法是protected native修飾,因此只暴露給之類(lèi)去重寫(xiě),外部是無(wú)法直接調(diào)用的。
我們現(xiàn)在來(lái)測(cè)試兩種復(fù)制,首選是淺復(fù)制,淺復(fù)制要實(shí)現(xiàn)Cloneable接口。
// 課程對(duì)象
class Class {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
// 學(xué)生對(duì)象
class User implements Cloneable {
private String name;
private Long id;
// 課程引用
private Class c;
public Class getC() {
return c;
}
public void setC(Class c) {
this.c = c;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
public int hashCode() {
return super.hashCode();
}
@Override
public boolean equals(Object obj) {
if (obj instanceof User) {
User user = (User) obj;
if (this.id == user.getId() && this.getName() == user.getName()) {
return true;
}
if (user.getId().equals(this.id)
&& user.getName().equals(this.name)) {
return true;
}
return false;
} else
return false;
}
}
我們來(lái)測(cè)試:
User user1 = new User();
User user2 = user1;
User user3 = (User) user1.clone();
System.out.println(user1 == user2);
System.out.println(user3 == user1);
System.out.println(user3.equals(user1));
System.out.println(user3.getName() == user3.getName());// true,淺復(fù)制
Class c = new Class();
c.setName("語(yǔ)文");
user1.setC(c);
// 測(cè)試復(fù)制深度
User user4 = (User) user1.clone();
System.out.println(user4.getC() == user1.getC()); // true,說(shuō)明引用的對(duì)象依然是同一個(gè)對(duì)象
對(duì)象的復(fù)制并沒(méi)復(fù)制引用所指向的對(duì)象class,復(fù)制出來(lái)的引用指向的同一個(gè)地址。
深復(fù)制采用序列化與反序列的方式去獲取,也有種說(shuō)法類(lèi)似于腌菜,用流的方式腌制進(jìn)去又取出來(lái),實(shí)現(xiàn)深度復(fù)制。
class Car implements Serializable {
/**
*
*/
private static final long serialVersionUID = 42342L;
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
// 深復(fù)制
class People implements Serializable{
/**
*
*/
private static final long serialVersionUID = 543535212412L;
private Car car;
public Car getCar() {
return car;
}
public void setCar(Car car) {
this.car = car;
}
public People deepClone() throws IOException, ClassNotFoundException {
// 腌制
ByteArrayOutputStream out = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(out);
oos.writeObject(this);
// 取出
ByteArrayInputStream input = new ByteArrayInputStream(out.toByteArray());
ObjectInputStream ois = new ObjectInputStream(input);
return (People) ois.readObject();
}
}
測(cè)試深復(fù)制:
// 深復(fù)制
Car car = new Car();
car.setName("benz");
People p = new People();
p.setCar(car);
try {
People p2 = p.deepClone();
System.out.println(p2.getCar() == p.getCar()); // false,說(shuō)明引用的對(duì)象也進(jìn)行了復(fù)制
} catch (ClassNotFoundException | IOException e) {
e.printStackTrace();
}
例外提及一下生成對(duì)象的五種辦法:
1.new
2.Class類(lèi)的newInstance
3.Constructor類(lèi)newInstance
4.Clone方式
5.反序列化的方式
其中2與3即是反射的方式。
感謝閱讀,希望能幫助到大家,謝謝大家對(duì)本站的支持!
- 利用Java反射機(jī)制實(shí)現(xiàn)對(duì)象相同字段的復(fù)制操作
- Java對(duì)象的復(fù)制三種方式(小結(jié))
- Java編程實(shí)現(xiàn)對(duì)象克隆(復(fù)制)代碼詳解
- Java中對(duì)象的深復(fù)制(深克?。┖蜏\復(fù)制(淺克隆)介紹
- 深入java對(duì)象復(fù)制的分析
- Java基礎(chǔ)之面向?qū)ο髾C(jī)制(多態(tài)、繼承)底層實(shí)現(xiàn)
- Java MapStruct解了對(duì)象映射的毒
- 詳解Java對(duì)象的內(nèi)存布局
- Java基礎(chǔ)詳解之面向?qū)ο蟮哪切┦聝?/a>
- 深入理解Java對(duì)象復(fù)制
相關(guān)文章
java中重寫(xiě)equals和重寫(xiě)hashCode()
這篇文章主要介紹了java中重寫(xiě)equals和重寫(xiě)hashCode()的相關(guān)資料,需要的朋友可以參考下2017-04-04
為SpringBoot服務(wù)添加HTTPS證書(shū)的方法
這篇文章主要介紹了為SpringBoot服務(wù)添加HTTPS證書(shū)的方法,幫助大家更好的理解和使用springBoot框架,感興趣的朋友可以了解下2020-10-10
解決java main函數(shù)中的args數(shù)組傳值問(wèn)題
這篇文章主要介紹了解決java main函數(shù)中的args數(shù)組傳值問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-02-02
Spring Boot單元測(cè)試中使用mockito框架mock掉整個(gè)RedisTemplate的示例
今天小編就為大家分享一篇關(guān)于Spring Boot單元測(cè)試中使用mockito框架mock掉整個(gè)RedisTemplate的示例,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2018-12-12
maven中心倉(cāng)庫(kù)OSSRH使用簡(jiǎn)介(推薦)
這篇文章主要介紹了maven中心倉(cāng)庫(kù)OSSRH使用簡(jiǎn)介,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-04-04
JAVA 數(shù)據(jù)結(jié)構(gòu)之Queue處理實(shí)例代碼
這篇文章主要介紹了JAVA 數(shù)據(jù)結(jié)構(gòu)之Queue處理實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下2017-02-02
SpringBoot中的@RestControllerAdvice注解詳解
這篇文章主要介紹了SpringBoot中的@RestControllerAdvice注解詳解,RestControllerAdvice注解用于創(chuàng)建全局異常處理類(lèi),用于捕獲和處理整個(gè)應(yīng)用程序中的異常,需要的朋友可以參考下2024-01-01
關(guān)于springboot集成swagger及knife4j的增強(qiáng)問(wèn)題
這篇文章主要介紹了springboot集成swagger以及knife4j的增強(qiáng),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-03-03

