網站首頁 編程語言 正文
創建Java對象的方式包括new、反射、反序列化、拷貝,那么什么是拷貝呢?淺拷貝和深拷貝又有什么區別呢?
什么是拷貝
拷貝就是為了復用原對象的部分或全部數據,在原對象的基礎上通過復制的方式創建一個新的對象。
Object類中有native類型的clone方法
protected native Object clone() throws CloneNotSupportedException;
復制代碼
如果一個對象可以被拷貝,那么該對象對應的類需要實現Cloneable接口,并重寫Object的clone方法。
必須實現Cloneable接口,否則調用clone方法會拋出
java.lang.CloneNotSupportedExecption異常
//Cloneable接口中沒有任何參數或抽象方法,該接口只是一個標識
public interface Cloneable {
}
復制代碼
//如Student類,實現Cloneable接口,重寫Object的clone方法
public class Student implements Cloneable{
private String sname;
private Integer sage;
...
@Override
protected Student clone() throws CloneNotSupportedException {
return (Student) super.clone();
}
}
復制代碼
舉個栗子
public class cloneObject {
public static void main(String[] args) throws CloneNotSupportedException {
Student student = new Student("學生1",18);
System.out.println("clone前的Student對象為:"+student);
Student cloneStudent = student.clone();
System.out.println("clone后的Student對象為:"+cloneStudent);
System.out.println("Student對象與cloneStudent對象是否相等:"+student.equals(cloneStudent));
}
}
復制代碼
打印結果為
clone前的Student對象為:Student{sname='學生1', sage=18}
clone后的Student對象為:Student{sname='學生1', sage=18}
Student對象與cloneStudent對象是否相等:false
復制代碼
由此可見,拷貝是創建了一個新的對象。
什么是淺拷貝?
我稍等改動下Student類來舉例說明
Student類中除了String類型和Integer類型的屬性外,添加了一個Teacher類型的屬性,Teacher類中只有一個String類型的tname屬性
public class Student implements Cloneable{
private String sname;
private Integer sage;
private Teacher teacher;
...
@Override
protected Student clone() throws CloneNotSupportedException {
return (Student) super.clone();
}
復制代碼
public class Teacher {
private String tname;
復制代碼
再次調用sutdent對象的clone方法
public static void main(String[] args) throws CloneNotSupportedException {
Teacher teacher = new Teacher("老師");
Student student = new Student("學生1",18,teacher);
System.out.println("clone前的Student對象為:"+student);
Student cloneStudent = student.clone();
System.out.println("clone后的Student對象為:"+cloneStudent);
System.out.println("Student對象與cloneStudent對象是否相等:"+student.equals(cloneStudent));
System.out.println("student對象和cloneStudent對象中的teacher屬性是否相等:"+student.getTeacher().equals(cloneStudent.getTeacher()));
}
復制代碼
兩個sutdent對象比較結果在意料之中,為false。但是兩種student對象中的teacher屬性比較結果卻是true。
clone前的Student對象為:Student{sname='學生1', sage=18, teacher=com.hard.qz.clone.Teacher@1b6d3586}
clone后的Student對象為:Student{sname='學生1', sage=18, teacher=com.hard.qz.clone.Teacher@1b6d3586}
Student對象與cloneStudent對象是否相等:false
student對象和cloneStudent對象中的teacher屬性是否相等:true
復制代碼
//修改student對象中teacher屬性的值,觀察cloneStudent對象中的teacher屬性的值是否會變
student.getTeacher().setTname("張三老師");
System.out.println("cloneStudent對象中teacher屬性的值為:"+cloneStudent.getTeacher());
復制代碼
結果為:
cloneStudent對象中teacher屬性的值為:Teacher{tname='張三老師'}
復制代碼
當修改student對象中teacher屬性的值時,會影響到cloneStudent對象中teacher屬性的值 由此說明:兩個student對象共用一個teacher對象。
像上面這種情況,當拷貝時,只拷貝了部分屬性,沒有拷貝Object和數組屬性時,這種拷貝被稱為淺拷貝。
什么是深拷貝?
當拷貝時,拷貝了一個對象中的所有屬性,包括Object和數組屬性,這種拷貝被稱為深拷貝
如何實現深拷貝?
重寫clone方法時,對Object和數組屬性也調用clone方法就可以實現深拷貝,要求被拷貝對象的Object屬性也實現Cloneable接口,重寫了clone方法。
//Teacher類實現了Cloneable接口,重寫了clone方法
public class Teacher implements Cloneable{
private String tname;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
//Student類重寫clone方法時,調用了Teacher類的clone方法,實現深拷貝
@Override
protected Student clone() throws CloneNotSupportedException {
Student cloneStudent = (Student) super.clone();
cloneStudent.setTeacher((Teacher) cloneStudent.getTeacher().clone());
return cloneStudent;
}
復制代碼
對student對象拷貝并比較兩個對象及對象中的屬性是否相等。
public class cloneObject {
public static void main(String[] args) throws CloneNotSupportedException {
Teacher teacher = new Teacher("老師");
Student student = new Student("學生1",18,teacher);
System.out.println("clone前的Student對象為:"+student);
Student cloneStudent = student.clone();
System.out.println("clone后的Student對象為:"+cloneStudent);
System.out.println("Student對象與cloneStudent對象是否相等:"+student.equals(cloneStudent));
System.out.println("student對象和cloneStudent對象中的teacher屬性是否相等:"+student.getTeacher().equals(cloneStudent.getTeacher()));
//修改student對象中teacher屬性的值,觀察cloneStudent對象中的teacher屬性的值是否會變
student.getTeacher().setTname("張三老師");
System.out.println("cloneStudent對象中teacher屬性的值為:"+cloneStudent.getTeacher());
}
}
復制代碼
打印結果為
clone前的Student對象為:Student{sname='學生1', sage=18, teacher=Teacher{tname='老師'}}
clone后的Student對象為:Student{sname='學生1', sage=18, teacher=Teacher{tname='老師'}}
Student對象與cloneStudent對象是否相等:false
student對象和cloneStudent對象中的teacher屬性是否相等:false
cloneStudent對象中teacher屬性的值為:Teacher{tname='老師'}
復制代碼
打印結果顯示深拷貝后的兩個對象及其中的屬性都不相等。
總結
- 拷貝是為了部分或全部復用原對象的屬性,在原對象的基礎上創建一個新的對象。
- 淺拷貝是拷貝后兩個對象地址不相等,但兩個對象的部分屬性地址相等,新對象并沒有拷貝所有的屬性,而是復用原對象中的值。
- 深拷貝是拷貝后兩個對象不僅地址不相等,兩個對象的所有屬性地址都不相等。
原文鏈接:https://blog.csdn.net/weixin_45985053/article/details/125858305
- 上一篇:Linux應該怎么使用命令
- 下一篇:分布式事務其中的那些坑
相關推薦
- 2022-08-15 element的form表單中如何一行顯示多el-form-item標簽
- 2022-06-30 C語言中結構體的內存對齊規則講解_C 語言
- 2022-04-12 GitHub_git push出現[rejected] master -> master (non-
- 2022-06-09 ASP.NET?Core使用EF創建模型(必需和可選屬性、最大長度、并發標記、陰影屬性)_實用技巧
- 2022-06-04 C#復雜XML反序列化為實體對象兩種方式小結_C#教程
- 2023-10-24 ElementUI日期選擇器DatePicker限制所選時間范圍(例如限制前后時長不超一個月)的實現
- 2024-03-25 使用HttpURLConnection發送POST請求并攜帶請求參數
- 2022-05-09 Python的ini配置文件你了解嗎_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支