## 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专题五:持久化