Java基础札记 - 对象深浅拷贝

浅拷贝:基本类型直接拷贝,引用类型拷贝内存地址! 【可以直接通过 impliment Cloneable 来实现浅拷贝】

public class AddressEntity implements Cloneable {

private String city;
private String country;

public AddressEntity(String city, String country) {
    this.city = city;
    this.country = country;
}

// 省略get、set
@Override
public Object clone() {
    try {
        return super.clone();
    } catch (CloneNotSupportedException e) {
        e.printStackTrace();
    }
    return null;
}

}
public class PersonEntity implements Cloneable {

private String username;
private int age;
private AddressEntity address;

@Override
public PersonEntity clone() {
    try {
        return (PersonEntity) super.clone();
    } catch (CloneNotSupportedException e) {
        return null;
    }
}

}
public static void cloneQian() {

AddressEntity address = new AddressEntity("杭州", "中国");
PersonEntity p1 = new PersonEntity("骆佳俊", 24, address);

// 拷贝对象
PersonEntity p2 = p1.clone();

// 原始对象和拷贝对象是否一样:
System.out.println("原始对象和拷贝对象是否一样: " + (p1 == p2));
// 原始对象和拷贝对象的name属性是否一样
System.out.println("原始对象和拷贝对象的name属性是否一样: " + (p1.getUsername() == p2.getUsername()));
// 原始对象和拷贝对象的subj属性是否一样
System.out.println("原始对象和拷贝对象的subj属性是否一样: " + (p1.getAddress() == p2.getAddress()));

p2.setUsername("ccc");
p2.getAddress().setCity("宁波");
System.out.println("更新后的原始对象: " + p1.getUsername() + " - " + p1.getAddress().getCity());
System.out.println("更新原始对象后的克隆对象: " + p2.getUsername() + " - " + p2.getAddress().getCity());

}

深拷贝:在对引用数据类型进行拷贝的时候,创建了一个新的对象,并且复制其内的成员变量。

实现方式:

  1. 实现cloneable接口

继续利用 clone()方法,对其内的引用类型的变量,再进行一次clone(),或者在clone()创建新的引用变量赋值和新的对象

public PersonEntity deepClone() throws CloneNotSupportedException {
    PersonEntity personClone = (PersonEntity) super.clone();
    personClone.address = (AddressEntity) this.address.clone();
    return personClone;
}
public static void deepClone() throws CloneNotSupportedException {
    AddressEntity address = new AddressEntity("杭州", "中国");
    PersonEntity p1 = new PersonEntity("骆佳俊", 24, address);
    PersonEntity p2 = p1.deepClone();
    p1.setAddress(new AddressEntity("宁波", "中国"));
    System.out.println(p2.getAddress());
    System.out.println(p1.getAddress());
    //AddressEntity{city='杭州', country='中国'}
    //AddressEntity{city='宁波', country='中国'}
}

最重要的代码就在 PersonEntity.clone() 中,它对其内的address ,再进行了一次 clone() 操作!

  1. 序列化与反序列化

序列化后将二进制字节流内容写到一个媒介(文本或字节数组),然后是从这个媒介读取数据,原对象写入这个媒介后拷贝给clone对象,原对象的修改不会影响clone对象,因为clone对象是从这个媒介读取。

public class AddressSearizableEntity implements Serializable {

private String city;
private String country;

@Override
public String toString() {
    return "AddressSearizableEntity{" +
            "city='" + city + '\'' +
            ", country='" + country + '\'' +
            '}';
}

// 省略get、set

}
public class PersonSerializableEntity implements Serializable {

private String username;
private int age;

// 省略get、set

public PersonSerializableEntity myClone() throws IOException, ClassNotFoundException {
    //序列化
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    ObjectOutputStream oos = null;
    try {
        oos = new ObjectOutputStream(bos);
        oos.writeObject(this);
    } catch (IOException e) {
        e.printStackTrace();
    }
    //反序列化
    ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
    ObjectInputStream ois = null;
    try {
        ois = new ObjectInputStream(bis);
    } catch (IOException e) {
        e.printStackTrace();
    }
    return (PersonSerializableEntity) ois.readObject();
}

}
public static void main(String[] args) throws CloneNotSupportedException {

    SpringApplication.run(HouseManageMentApplication.class, args);
    PersonSerializableEntity p1 = new PersonSerializableEntity("roger", 24, new AddressSearizableEntity("杭州", "中国"));
    try {
        PersonSerializableEntity p2 = p1.myClone();
        p2.setAddress(new AddressSearizableEntity("宁波", "中国"));
        //AddressSearizableEntity{city='杭州', country='中国'},AddressSearizableEntity{city='宁波', country='中国'}
        System.out.println(p1.getAddress() + "," + p2.getAddress());
    } catch (IOException e) {
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }

}

你可能感兴趣的:(java拷贝构造函数)