main方法
public static void main(String[] args) throws Exception {
CopyTest copyTest = new CopyTest();
copyTest.setName("张三");
CopyTest.Address address = copyTest.new Address();
address.setCity("杭州");
address.setProvince("浙江");
copyTest.setAddress(address);
CopyTest copyTest1 = (CopyTest) copyTest.clone();
System.out.println(JSON.toJSONString(copyTest1));
copyTest1.getAddress().setProvince("上海");
copyTest1.setName("李四");
System.out.println(JSON.toJSONString(copyTest));
System.out.println(JSON.toJSONString(copyTest1));
}
1.浅拷贝
/**
* @Classname CopyTest
* @Description
* @Date 2020-07-10 14:20
* @Created by myc
*/
public class CopyTest implements Cloneable {
private String name;
private Address address;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public class Address {
String province;
String city;
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
}
}
结果如下:
{"address":{"city":"杭州","province":"浙江"},"name":"张三"}
{"address":{"city":"杭州","province":"上海"},"name":"张三"}
{"address":{"city":"杭州","province":"上海"},"name":"李四"}
特点:
(1) 对于基本数据类型的成员对象,因为基础数据类型是值传递的,所以是直接将属性值赋值给新的对象。基础类型的拷贝,其中一个对象修改该值,不会影响另外一个。
(2) 对于引用类型,比如数组或者类对象,因为引用类型是引用传递,所以浅拷贝只是把内存地址赋值给了成员变量,它们指向了同一内存空间。改变其中一个,会对另外一个也产生影响
2.深拷贝(一)
通过实现Cloneable接口
/**
* @Classname CopyTest
* @Description
* @Date 2020-07-10 14:20
* @Created by myc
*/
public class CopyTest implements Cloneable {
private String name;
private Address address;
@Override
protected Object clone() throws CloneNotSupportedException {
CopyTest copyTest = (CopyTest) super.clone();
copyTest.address = (Address) address.clone();
return copyTest;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public class Address implements Cloneable{
String province;
String city;
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public String getCity() {
return city;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
public void setCity(String city) {
this.city = city;
}
}
}
结果如下:
{"address":{"city":"杭州","province":"浙江"},"name":"张三"}
{"address":{"city":"杭州","province":"浙江"},"name":"张三"}
{"address":{"city":"杭州","province":"上海"},"name":"李四"}
3.深拷贝(二)
通过实现Serializable接口序列化
import java.io.*;
/**
* @Classname CopyTest
* @Description
* @Date 2020-07-10 14:20
* @Created by myc
*/
public class CopyTest implements Serializable {
private String name;
private Address address;
@Override
protected Object clone() throws CloneNotSupportedException {
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(bos);
out.writeObject(this);
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream is = new ObjectInputStream(bis);
return is.readObject();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public class Address implements Serializable{
String province;
String city;
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
}
}
结果如下:
{"address":{"city":"杭州","province":"浙江"},"name":"张三"}
{"address":{"city":"杭州","province":"浙江"},"name":"张三"}
{"address":{"city":"杭州","province":"上海"},"name":"李四"}
特点:
(1) 对于基本数据类型的成员对象,因为基础数据类型是值传递的,所以是直接将属性值赋值给新的对象。基础类型的拷贝,其中一个对象修改该值,不会影响另外一个(和浅拷贝一样)。
(2) 对于引用类型,比如数组或者类对象,深拷贝会新建一个对象空间,然后拷贝里面的内容,所以它们指向了不同的内存空间。改变其中一个,不会对另外一个也产生影响。
(3) 对于有多层对象的,每个对象都需要实现 Cloneable 并重写 clone() 方法,进而实现了对象的串行层层拷贝,或者通过序列化实现。
(4) 深拷贝相比于浅拷贝速度较慢并且花销较大。