[Java] 浅拷贝与深拷贝
程序员文章站
2022-05-28 14:37:04
...
Java 中的拷贝分为浅拷贝和深拷贝两种,其中浅拷贝指只拷贝按值传递的数据类型,如基本数据类型、String 类型;而深拷贝除了拷贝浅拷贝的内容外,还负责拷贝引用类型的数据。
一、浅拷贝示例:
主要部分为:
@Override
protected Object clone() {
Object obj = null;
try {
obj = super.clone();
} catch (Exception e) {
e.printStackTrace();
}
return obj;
}
详细示例如下:
package com.kascend.test.copy;
/**
* 浅拷贝对象
*
* @author wengliemiao
*/
public class SimpleCopy implements Cloneable {
private int id;
private String name;
private String signature;
/**
* 获取 id
*
* @return id
*/
public int getId() {
return id;
}
/**
* 设置 id
*
* @param id
*/
public void setId(int id) {
this.id = id;
}
/**
* 获取 name
*
* @return name
*/
public String getName() {
return name;
}
/**
* 设置 name
*
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取 signature
*
* @return signature
*/
public String getSignature() {
return signature;
}
/**
* 设置 signature
*
* @param signature
*/
public void setSignature(String signature) {
this.signature = signature;
}
@Override
protected Object clone() {
Object obj = null;
try {
obj = super.clone();
} catch (Exception e) {
e.printStackTrace();
}
return obj;
}
@Override
public String toString() {
return "SimpleCopy{" +
"id=" + id +
", name='" + name + '\'' +
", signature='" + signature + '\'' +
'}';
}
}
package com.kascend.test.copy;
/**
* 浅拷贝测试类
*
* @author wengliemiao
*/
public class CopyTest {
public static void main(String[] args) {
SimpleCopy simpleCopy = new SimpleCopy();
simpleCopy.setId(1);
simpleCopy.setName("wlmmm");
simpleCopy.setSignature("a java programmer");
System.out.println("浅拷贝前: ");
System.out.println(simpleCopy);
SimpleCopy newSimpleCopy = (SimpleCopy) simpleCopy.clone();
newSimpleCopy.setSignature("a handsome java programmer");
System.out.println("浅拷贝的对象: ");
System.out.println(newSimpleCopy);
System.out.println("浅拷贝后: ");
System.out.println(simpleCopy);
}
}
输出为:
二、深拷贝示例:
主要部分为:
@Override
protected Object clone() {
DeepCopy obj = null;
try {
obj = (DeepCopy) super.clone();
obj.setPosition((Position) obj.getPosition().clone());
} catch (Exception e) {
e.printStackTrace();
}
return obj;
}
详细示例如下:
package com.kascend.test.copy;
/**
* 深拷贝对象
*
* @author wengliemiao
*/
public class DeepCopy implements Cloneable {
private int id;
private String name;
private String signature;
private Position position;
/**
* 获取 id
*
* @return id
*/
public int getId() {
return id;
}
/**
* 设置 id
*
* @param id
*/
public void setId(int id) {
this.id = id;
}
/**
* 获取 name
*
* @return name
*/
public String getName() {
return name;
}
/**
* 设置 name
*
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取 signature
*
* @return signature
*/
public String getSignature() {
return signature;
}
/**
* 设置 signature
*
* @param signature
*/
public void setSignature(String signature) {
this.signature = signature;
}
/**
* 获取 position
*
* @return position
*/
public Position getPosition() {
return position;
}
/**
* 设置 position
*
* @param position
*/
public void setPosition(Position position) {
this.position = position;
}
@Override
protected Object clone() {
DeepCopy obj = null;
try {
obj = (DeepCopy) super.clone();
obj.setPosition((Position) obj.getPosition().clone());
} catch (Exception e) {
e.printStackTrace();
}
return obj;
}
@Override
public String toString() {
return "DeepCopy{" +
"id=" + id +
", name='" + name + '\'' +
", signature='" + signature + '\'' +
", position=" + position +
'}';
}
}
package com.kascend.test.copy;
/**
* 地理位置对象
*
* @author wengliemiao
*/
public class Position implements Cloneable {
/**
* 省份
*/
private String province;
/**
* 城市
*/
private String city;
public Position(String province, String city) {
this.province = province;
this.city = city;
}
/**
* 获取 province
*
* @return province
*/
public String getProvince() {
return province;
}
/**
* 设置 province
*
* @param province
*/
public void setProvince(String province) {
this.province = province;
}
/**
* 获取 city
*
* @return city
*/
public String getCity() {
return city;
}
/**
* 设置 city
*
* @param city
*/
public void setCity(String city) {
this.city = city;
}
@Override
protected Object clone() {
Object obj = null;
try {
obj = super.clone();
} catch (Exception e) {
e.printStackTrace();
}
return obj;
}
@Override
public String toString() {
return "Position{" +
"province='" + province + '\'' +
", city='" + city + '\'' +
'}';
}
}
package com.kascend.test.copy;
/**
* 深拷贝测试类
*
* @author wengliemiao
*/
public class DeepCopyTest {
public static void main(String[] args) {
DeepCopy deepCopy = new DeepCopy();
deepCopy.setId(1);
deepCopy.setName("wlmmm");
deepCopy.setSignature("a java programmer");
deepCopy.setPosition(new Position("浙江", "杭州"));
System.out.println("深拷贝前: ");
System.out.println(deepCopy);
DeepCopy newDeepCopy = (DeepCopy) deepCopy.clone();
newDeepCopy.setSignature("a handsome java programmer");
newDeepCopy.getPosition().setProvince("江西");
newDeepCopy.getPosition().setCity("上饶");
System.out.println("深拷贝的对象: ");
System.out.println(newDeepCopy);
System.out.println("深拷贝后: ");
System.out.println(deepCopy);
}
}
输出为:
深拷贝需要注意的地方:需要递归拷贝所有的引用类型属性,如果有一个没有正确实现拷贝,则会失败。
三、序列化方式实现深拷贝
主要部分为:
@Override
protected Object clone() {
Object obj = null;
try {
// 写入到流中
ByteArrayOutputStream bao = new ByteArrayOutputStream();
ObjectOutputStream oo = new ObjectOutputStream(bao);
oo.writeObject(this);
// 从流中读取
ByteArrayInputStream bai = new ByteArrayInputStream(bao.toByteArray());
ObjectInputStream oi = new ObjectInputStream(bai);
obj = oi.readObject();
} catch (Exception e) {
e.printStackTrace();
}
return obj;
}
详细示例如下:
package com.kascend.test.copy;
import java.io.*;
/**
* 深拷贝序列化对象
*
* @author wengliemiao
*/
public class DeepCopySerializer implements Serializable {
private static final long serialVersionUID = 2613335614834345944L;
private int id;
private String name;
private String signature;
private PositionSerializer positionSerializer;
/**
* 获取 id
*
* @return id
*/
public int getId() {
return id;
}
/**
* 设置 id
*
* @param id
*/
public void setId(int id) {
this.id = id;
}
/**
* 获取 name
*
* @return name
*/
public String getName() {
return name;
}
/**
* 设置 name
*
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取 signature
*
* @return signature
*/
public String getSignature() {
return signature;
}
/**
* 设置 signature
*
* @param signature
*/
public void setSignature(String signature) {
this.signature = signature;
}
/**
* 获取 positionSerializer
*
* @return positionSerializer
*/
public PositionSerializer getPositionSerializer() {
return positionSerializer;
}
/**
* 设置 positionSerializer
*
* @param positionSerializer
*/
public void setPositionSerializer(PositionSerializer positionSerializer) {
this.positionSerializer = positionSerializer;
}
@Override
public String toString() {
return "DeepCopySerializer{" +
"id=" + id +
", name='" + name + '\'' +
", signature='" + signature + '\'' +
", positionSerializer=" + positionSerializer +
'}';
}
@Override
protected Object clone() {
Object obj = null;
try {
// 写入到流中
ByteArrayOutputStream bao = new ByteArrayOutputStream();
ObjectOutputStream oo = new ObjectOutputStream(bao);
oo.writeObject(this);
// 从流中读取
ByteArrayInputStream bai = new ByteArrayInputStream(bao.toByteArray());
ObjectInputStream oi = new ObjectInputStream(bai);
obj = oi.readObject();
} catch (Exception e) {
e.printStackTrace();
}
return obj;
}
}
package com.kascend.test.copy;
import java.io.Serializable;
/**
* 地理位置序列化对象
*
* @author wengliemiao
*/
public class PositionSerializer implements Serializable {
private static final long serialVersionUID = 4079422724081087207L;
private String province;
private String city;
public PositionSerializer(String province, String city) {
this.province = province;
this.city = city;
}
/**
* 获取 province
*
* @return province
*/
public String getProvince() {
return province;
}
/**
* 设置 province
*
* @param province
*/
public void setProvince(String province) {
this.province = province;
}
/**
* 获取 city
*
* @return city
*/
public String getCity() {
return city;
}
/**
* 设置 city
*
* @param city
*/
public void setCity(String city) {
this.city = city;
}
@Override
public String toString() {
return "Position2{" +
"province='" + province + '\'' +
", city='" + city + '\'' +
'}';
}
}
package com.kascend.test.copy;
/**
* 序列化实现深拷贝测试类
*
* @author wengliemiao
*/
public class DeepCopySerializerTest {
public static void main(String[] args) {
DeepCopySerializer deepCopySerializer = new DeepCopySerializer();
deepCopySerializer.setId(1);
deepCopySerializer.setName("wlmmm");
deepCopySerializer.setSignature("a java programmer");
deepCopySerializer.setPositionSerializer(new PositionSerializer("浙江", "杭州"));
System.out.println("序列化方式深拷贝前: ");
System.out.println(deepCopySerializer);
DeepCopySerializer newDeepCopy = (DeepCopySerializer) deepCopySerializer.clone();
newDeepCopy.setSignature("a handsome java programmer");
newDeepCopy.getPositionSerializer().setProvince("江西");
newDeepCopy.getPositionSerializer().setCity("上饶");
System.out.println("序列化方式深拷贝对象: ");
System.out.println(newDeepCopy);
System.out.println("序列化方式深拷贝后: ");
System.out.println(deepCopySerializer);
}
}
输出为:
小结:序列化实现深拷贝的方式在很多框架中应用,可省去实现 Cloneable
接口的复杂繁琐的操作。如常用的 memcached 缓存,要求需要放入缓存中的对象实现 Serializable
接口。
注:序列化实现深拷贝参考自: java对象克隆以及深拷贝和浅拷贝
上一篇: 前端学习记录 Day1(Html)
下一篇: java:深拷贝与浅拷贝