我们在平时的开发中难免会遇到对象的复制问题。对于一些定义简单的对象(所有属性都为基本类型),如果直接赋值操作,相当于两个对象共用一个地址。修改其中那个对象的属性值,另一个的属性值也会一起变化。如果我们想让它们两个各自分配空间,就需要用到对象的拷贝。对于对象中只有基本类型属性的对象我们可以使用浅拷贝。
浅拷贝实现方式:
首先让定义的实体类实现Cloneable接口。然后重写clone方法,将clone方法的修饰符由protected改为public。这样就可以通过调用clone方法进行浅拷贝。
实现代码及测试如下:
public class Man implements Cloneable {
private String name;
private String sex;
private int old;
public Man(String name, String sex, int old) {
super();
this.name = name;
this.sex = sex;
this.old = old;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getOld() {
return old;
}
public void setOld(int old) {
this.old = old;
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
public String toString() {
return "Man [name=" + name + ", sex=" + sex + ", old=" + old + "]";
}
public static void main(String[] args) throws CloneNotSupportedException {
Man m1 = new Man("张三", "男", 25);
Man m2 = (Man) m1.clone();
m1.setName("李四");//修改对象1的值看两个对象值得变化情况
System.out.println(m1.toString());
System.out.println(m2.toString());
m2.setSex("女");//修改对象2的值看两个对象值得变化情况
System.out.println(m1.toString());
System.out.println(m2.toString());
}
}
执行结果如图:
但是包含引用类型属性的对象a在赋值给b后,如果修改对象a中的引用类型属性,b中的该属性也会发生变化。这样的复制是不合逻辑的。我们希望a和b对象是相互独立的,修改其中一个的属性不会影响另一个的属性。这就要用到深拷贝了。
浅拷贝无法解决引用属性的赋值问题。如下图代码所示:
class Children {
private String name;
private String sex;
int old;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getOld() {
return old;
}
public void setOld(int old) {
this.old = old;
}
public Children(String name, String sex, int old) {
super();
this.name = name;
this.sex = sex;
this.old = old;
}
@Override
public String toString() {
return "Children [name=" + name + ", sex=" + sex + ", old=" + old + "]";
}
}
public class Man implements Cloneable {
private String name;
private String sex;
private int old;
private Children ch;
public Man(String name, String sex, int old, Children ch) {
super();
this.name = name;
this.sex = sex;
this.old = old;
this.ch = ch;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getOld() {
return old;
}
public void setOld(int old) {
this.old = old;
}
public Children getCh() {
return ch;
}
public void setCh(Children ch) {
this.ch = ch;
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
public String toString() {// 将chlidren对象内部属性打印
return "Man [name=" + name + ", sex=" + sex + ", old=" + old + ", ch=" + ch.toString() + "]";
}
public static void main(String[] args) throws CloneNotSupportedException {
Man m1 = new Man("张三", "男", 25, new Children("张小宝", "男", 5));
Man m2 = (Man) m1.clone();
Children ch = m1.getCh();
ch.setName("王小丫");
ch.setSex("女");
System.out.println(m1.toString());
System.out.println(m2.toString());
ch = m2.getCh();
ch.setName("张小柱");
ch.setSex("男");
System.out.println(m1.toString());
System.out.println(m2.toString());
}
}
执行结果如图:
深拷贝实现方式:
首先是将引用的实体类也实现Cloneable接口(同时重写clone方法,也是修改修饰符为public)。然后同样是让定义的实体类实现Cloneable接口。然后重写clone方法,将clone方法的修饰符由protected改为public。但是方法体需要进行重写,将引用的对象属性调用它本身的clone方法进行赋值,然后将赋值后的对象返回即可。
具体代码如下(结合上一段代码):
@Override
public Object clone() throws CloneNotSupportedException {
Man man = (Man) super.clone();
man.setCh((Children) man.getCh().clone());
return man;
}
写完深拷贝的代码再次运行。结果如下:
这次两个对象就是完全独立,属性之间不存在共用同一个地址的情况了。
喜欢的朋友点个赞哦~~