## Java專題十九:淺拷貝與深拷貝
[TOC]
### 19.1. clone方法
`clone`方法是`Object`類提供的一個用于對象拷貝的方法,且是`protected`,使用時需要類實現`java.lang.Cloneable`接口,否則將拋出`CloneNotSupportedException`異常
~~~
// java.lang.Object
protected native Object clone() throws CloneNotSupportedException;
~~~
使用`clone`通常遵循的約定:
- `x.clone() != x`返回ture
- `x.clone().getClass() == x.getClass()`返回ture
- `x.clone().equals(x)`返回ture
### 19.2. 淺拷貝
- 對于基本數據類型字段,直接賦值給新的對象
- 對于引用數據類型字段,復制對象引用(對象地址)到新的對象
- **問題**:**對新對象中引用數據類型字段的修改會一同修改源對象引用數據類型字段,因為兩個字段引用的是同一個對象地址**
### 19.3. 深拷貝
- 對于基本數據類型字段,直接賦值給新的對象
- 對于引用數據類型字段,為字段構造一個新的對象,并將源對象字段中每一個子字段賦值到新的對象字段中
假設有一個`Person`類,有眼睛(`eye`字段)和性別(`sex`字段),其中`sex`是基本數據類型,`eye`是引用數據類型
~~~
public class Person{
public static final int SEX_MAN = 0;
public static final int SEX_WOMAN = 0;
private int sex;
private Eye eye;
public Person shallowCopy(){
Person dest = new Person();
dest.sex = this.sex;
dest.eye = this.eye;
return dest;
}
public Person deepCopy(){
Person dest = new Person();
dest.sex = this.sex;
dest.eye = this.eye.deepCopy();
return dest;
}
@Override
public String toString() {
StringBuffer buffer = new StringBuffer();
buffer.append(getClass().getName() + "@" + Integer.toHexString(hashCode()))
.append(": { ")
.append("sex: ").append(sex).append(", ")
.append("eye: ").append(eye.toString())
.append(" }");
return buffer.toString();
}
public int getSex() {
return sex;
}
public void setSex(int sex) {
this.sex = sex;
}
public Eye getEye() {
return eye;
}
public void setEye(Eye eye) {
this.eye = eye;
}
}
class Eye {
public static final String COLOR_BLACK = "black";
public static final String COLOR_BLUE = "blue";
private String color;
private int size;
public Eye(String color, int size){
this.color = color;
this.size = size;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public Eye deepCopy(){
return new Eye(this.color, this.size);
}
public String toString() {
StringBuffer buffer = new StringBuffer();
buffer.append(getClass().getName() + "@" + Integer.toHexString(hashCode()))
.append(": { ")
.append("color: ").append(color).append(", ")
.append("size: ").append(size)
.append(" }");
return buffer.toString();
}
}
~~~
### 19.4. 實現方法
#### 19.4.1. 淺拷貝
##### 19.4.1.1. 使用shalldowCopy方法
shalldowCopy為自定義的方法,在方法中,直接構造一個新對象,將源對象的每一個字段使用`=`賦值給新對象中,調用shalldowCopy()方法即可完成淺拷貝
##### 19.4.1.2. 使用clone方法
重寫`clone`方法,在類的`clone`方法種直接調用`super.clone()`,調用clone()方法即可完成淺拷貝
~~~
public class Person implements Cloneable {
public Person clone(){
Person dest = null;
try{
dest = (Person) super.clone();
} catch (CloneNotSupportedException e){
e.printStackTrace();
}
return dest;
}
}
~~~
#### 19.4.2. 深拷貝
##### 19.4.2.1. 使用deepCopy方法
deepCopy為自定義的方法,在方法中,直接構造一個新對象,對源對象的基本數據類型字段使用`=`賦值給新對象中,對于引用數據類型使用deepCopy方法賦值,調用deepCopy()方法即可完成深拷貝
##### 19.4.2.2. 使用clone方法
重寫`clone`方法,在類的`clone`方法種調用`super.clone()`,對于引用數據類型使用deepCopy方法賦值,調用clone()方法即可完成深拷貝
~~~
public class Person implements Cloneable {
public Person clone(){
Person dest = null;
try{
dest = (Person) super.clone();
dest.eye = dest.eye.deepCopy();
} catch (CloneNotSupportedException e){
e.printStackTrace();
}
return dest;
}
}
~~~
- JavaCook
- Java專題零:類的繼承
- Java專題一:數據類型
- Java專題二:相等與比較
- Java專題三:集合
- Java專題四:異常
- Java專題五:遍歷與迭代
- Java專題六:運算符
- Java專題七:正則表達式
- Java專題八:泛型
- Java專題九:反射
- Java專題九(1):反射
- Java專題九(2):動態代理
- Java專題十:日期與時間
- Java專題十一:IO與NIO
- Java專題十一(1):IO
- Java專題十一(2):NIO
- Java專題十二:網絡
- Java專題十三:并發編程
- Java專題十三(1):線程與線程池
- Java專題十三(2):線程安全與同步
- Java專題十三(3):內存模型、volatile、ThreadLocal
- Java專題十四:JDBC
- Java專題十五:日志
- Java專題十六:定時任務
- Java專題十七:JavaMail
- Java專題十八:注解
- Java專題十九:淺拷貝與深拷貝
- Java專題二十:設計模式
- Java專題二十一:序列化與反序列化
- 附加專題一:MySQL
- MySQL專題零:簡介
- MySQL專題一:安裝與連接
- MySQL專題二:DDL與DML語法
- MySQL專題三:工作原理
- MySQL專題四:InnoDB存儲引擎
- MySQL專題五:sql優化
- MySQL專題六:數據類型
- 附加專題二:Mybatis
- Mybatis專題零:簡介
- Mybatis專題一:配置文件
- Mybatis專題二:映射文件
- Mybatis專題三:動態SQL
- Mybatis專題四:源碼解析
- 附加專題三:Web編程
- Web專題零:HTTP協議
- Web專題一:Servlet
- Web專題二:Cookie與Session
- 附加專題四:Redis
- Redis專題一:數據類型
- Redis專題二:事務
- Redis專題三:key的過期
- Redis專題四:消息隊列
- Redis專題五:持久化