在讲拷贝之前我们,是不是遇到这样的问题
Obj oA = new Obj();
oA.setProto("属性1");
Obj oB = new Obj();
oB = oA;
oB.setProto("属性2");这是对象的赋值,oB经过赋值,得到的是oA地址的引用,二者无论谁改变任一属性,都会相互影响.
Java 中已经给我们提供了这样的API,无需我们遍历递归自己处理.
1.浅拷贝
就是将已知对象完整的拷贝一份给一个对象(注意:已知对象中成员变量若是对象,拷贝的是地址引用)
拷贝的深层含义是:拷一份一模一样的数据给另一个对象,当两个对象内容发生变化时,彼此不受影响(对象除外)
1.1 定义的对象实现Cloneable接口,虽然这个接口中并没有抽象方法,但是如果不实现的话,就会报错,因为super.clone()是Object的方法,可能其中用到了泛型为Cloneable的对象.
1.2 重写clone方法,因为Object中的clone方法是protect修饰的,子类不能直接使用.
public class Bean implements Cloneable{
String name;
public Bean(String name) {
this.name = name;
}
public Object clone() {
Bean o = null;
try {
o = (Bean) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return o;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}使用浅克隆的调用方法:
Bean bean = new Bean("张三");
Bean newBean = (Bean) bean.clone();
newBean.setName("李四");
System.out.println(bean.getName());结果是张三,说明bean 和newBean 中的成员变量又重新开辟了一块内存空间.
1.3 问题:如果我在Bean 中添加一个对象Person 或者List 或者数组会怎样?
你会发现,新对象中的Person 或者List 或者数组又和老对象 缠缠绵绵活的潇潇洒洒,好这就引入了深拷贝.
2.深拷贝
深拷贝就是将对象中的对象,也开辟一块内存空间并且赋值,那么要求对象也必须实现Cloneable,重写克隆方法.
并且在上层对象中调用clone 方法.代码中: o.person = (Person) person.clone();
public class Bean implements Cloneable {
String name;
Person person;
public Bean(String name, Person person) {
this.name = name;
this.person = person;
}
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
public Object clone() {
Bean o = null;
try {
o = (Bean) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
o.person = (Person) person.clone();
return o;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class Person implements Cloneable{
public String name;
public Person(String name) {
this.name = name;
}
public Object clone() {
Person o = null;
try {
o = (Person) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return o;
}
public String getName() {
return name;
}
public Person setName(String name) {
this.name = name;
return this;
}
}调用:
Bean bean = new Bean("张三",new Person("Persion"));
Bean newBean = (Bean) bean.clone();
newBean.setName("李四");
newBean.getPerson().setName("newPersion");
System.out.println(bean.getName()+"===="+bean.getPerson().getName());调用结果:张三====Persion
3.补充
若该类实现序列化接口Serializable 或者Parcelable(安卓API轻量级序列化)可以实现序列化.这个序列化不同于上面的深浅拷贝深浅拷贝指的是运行内存,序列化一般指的是外部存储.
这个就不举例了,我们想想,如果A对象序列化给B对象,A更改了属性值,B也跟着变了,是不是要哭了,显然不可能的.
,

本文详细介绍了Java中对象的浅拷贝与深拷贝的区别及实现方式,包括实现Cloneable接口与重写clone方法,并通过实例展示了如何进行深拷贝以避免对象间的相互影响。
1540

被折叠的 条评论
为什么被折叠?



