💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
## 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; } } ~~~