浅拷贝与深拷贝
浅拷贝的是对象的地址,栈中的两个地址指向堆中的同一块内存区域:
通过=获得的基本数据类型为深拷贝,获得的引用类型为浅拷贝。顾名思义,深拷贝就是要保证两个对象的所有成员都是独立的。
如何实现对象的深拷贝
方法一、对对象中所有的自定义引用数据类型实现Clonable接口重写clone方法,保证每一个成员变量都是拷贝出来的副本
示例代码:
Person类
package com.bean;
import java.io.Serializable;
public class Person implements Cloneable, Serializable{
String name;
Integer age;
//包含Address自定义对象,该类需要实现clonable接口并重写clone方法
Address address;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Person(String name, Integer age) {
this.name = name;
this.age = age;
address=new Address();
}
public Person(){
address=new Address();
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
@Override
public String toString() {
return "{name:"+this.name+",age:"+this.age+",adress:{province:"+this.address.getProvince()+",city:"+this.address.getCity()+"}}";
}
//实现clonable接口并重写clone方法
@Override
public Object clone() throws CloneNotSupportedException {
Person p=(Person) super.clone();
p.address=(Address) this.address.clone();
return p;
}
}
Address类
package com.bean;
import java.io.Serializable;
public class Address implements Cloneable, 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;
}
public Address(String province, String city) {
this.province = province;
this.city = city;
}
public Address() {
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
测试类:
package com.company;
import com.bean.*;
public class Main {
public static void main(String[] args) throws Exception {
Person p = new Person("张三", 15);
p.setAddress(new Address("湖北", "武汉"));
Person cp = (Person) p.clone();
//测试改变拷贝出来的示例是否会影响原来的实例
cp.setAddress(new Address("浙江", "杭州"));
System.out.println(p);
}
}
运行结果:
{name:张三,age:15,adress:{province:湖北,city:武汉}}
可以看出改变拷贝出来的实例的内容不会影响原来的实例。
方法二、将原对象序列化,然后反序列化,得到新的对象副本
Preson类及其成员变量对应的类都需要继承Serializable接口。
测试代码:
package com.company;
import com.bean.*;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class Main {
public static void main(String[] args) throws Exception {
Person p = new Person("张三", 15);
p.setAddress(new Address("湖北", "武汉"));
//序列化对象
ByteArrayOutputStream bos=new ByteArrayOutputStream();
ObjectOutputStream oos=new ObjectOutputStream(bos);
oos.writeObject(p);
//反序列化对象
ByteArrayInputStream bis=new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois=new ObjectInputStream(bis);
Person cp=(Person) ois.readObject();
//两个对象是否为同一个实例
System.out.println(p==cp);
//修改副本是否影响原实例
cp.setAddress(new Address("浙江","杭州"));
System.out.println("原实例:"+p);
System.out.println("实例副本:"+cp);
}
}
运行结果:
false
原实例:{name:张三,age:15,adress:{province:湖北,city:武汉}}
实例副本:{name:张三,age:15,adress:{province:浙江,city:杭州}}