基本概念
- 浅拷贝:
a.对于数据类型是基本数据类型的成员变量,浅拷贝会直接进行值传递,也就是将该属性值复制一份给新的对象。因为是两份不同的数据,所以对其中一个对象的该成员变量值进行修改,不会影响另一个对象拷贝得到的数据。
b.对于数据类型是引用数据类型的成员变量,比如说成员变量是某个数组、某个类的对象等,那么浅拷贝会进行引用传递,也就是只是将该成员变量的引用值(内存地址)复制一份给新的对象。因为实际上两个对象的该成员变量都指向同一个实例。在这种情况下,在一个对象中修改该成员变量会影响到另一个对象的该成员变量值。 - 深拷贝:区别于浅拷贝就在于对于引用类型是新建一个对象空间,拷贝对应内容,前后两者指向不同的内存空间,修改不会对互相产生影响。
浅拷贝实现
声明一个Province类,Address类,User类,User类中有Address引用,Address有Province引用
public class Province {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Province{" +
"name='" + name + '\'' +
'}';
}
}
public class Address {
private String detail;
private Province province;
public String getDetail() {
return detail;
}
public void setDetail(String detail) {
this.detail = detail;
}
public Province getProvince() {
return province;
}
public void setProvince(Province province) {
this.province = province;
}
@Override
public String toString() {
return "Address{" +
"detail='" + detail + '\'' +
", province=" + province +
'}';
}
}
public class User implements Cloneable {
private int sex;
private String username;
private Address address;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public int getSex() {
return sex;
}
public void setSex(int sex) {
this.sex = sex;
}
@Override
public Object clone() {
//浅拷贝
try {
// 直接调用父类的clone()方法
return super.clone();
} catch (CloneNotSupportedException e) {
return null;
}
}
@Override
public String toString() {
return "User{" +
"sex=" + sex +
", username='" + username + '\'' +
", address=" + address +
'}';
}
}
public class Test {
public static void main(String[] args) {
User user = new User();
Province province = new Province();
province.setName("江西");
Address address = new Address();
address.setDetail("江西南昌");
address.setProvince(province);
user.setUsername("小明");
user.setSex(1);
user.setAddress(address);
System.out.println(user);
User user1 = (User) user.clone();
System.out.println(user1);
System.out.println("修改");
user1.setSex(0);
user1.getAddress().setDetail("江西九江");
System.out.println(user);
System.out.println(user1);
}
}
执行结果可以发现,修改克隆对象,对于基础类型,是不会对源对象产生影响,而修改克隆对象的引用类型,会对源对象进行修改,因为他们指向同一个地址.
User{sex=1, username=‘小明’, address=Address{detail=‘江西南昌’, province=Province{name=‘江西’}}}
User{sex=1, username=‘小明’, address=Address{detail=‘江西南昌’, province=Province{name=‘江西’}}}
修改
User{sex=1, username=‘小明’, address=Address{detail=‘江西九江’, province=Province{name=‘江西’}}}
User{sex=0, username=‘小明’, address=Address{detail=‘江西九江’, province=Province{name=‘江西’}}}
深拷贝
对于每个引用类型都需要实现cloneable接口
Province
@Override
public Object clone(){
try {
// 直接调用父类的clone()方法
return super.clone();
} catch (CloneNotSupportedException e) {
return null;
}
}
Address
@Override
public Object clone(){
try {
Address address = (Address) super.clone();
address.province = (Province) this.province.clone();
return address;
} catch (CloneNotSupportedException e) {
return null;
}
}
User
@Override
public Object clone() {
try {
User user = (User) super.clone();
user.address = (Address) address.clone();
return user;
} catch (CloneNotSupportedException e) {
return null;
}
}
public class Test {
public static void main(String[] args) {
User user = new User();
Province province = new Province();
province.setName("江西");
Address address = new Address();
address.setDetail("江西南昌");
address.setProvince(province);
user.setUsername("小明");
user.setSex(1);
user.setAddress(address);
System.out.println(user);
User user1 = (User) user.clone();
System.out.println(user1);
System.out.println("修改");
user1.setSex(0);
user1.getAddress().setDetail("上海浦东");
user1.getAddress().getProvince().setName("上海");
System.out.println(user);
System.out.println(user1);
}
}
结果,对于引用类型的修改不会影响到源对象的修改
User{sex=1, username=‘小明’, address=Address{detail=‘江西南昌’, province=Province{name=‘江西’}}}
User{sex=1, username=‘小明’, address=Address{detail=‘江西南昌’, province=Province{name=‘江西’}}}
修改
User{sex=1, username=‘小明’, address=Address{detail=‘江西南昌’, province=Province{name=‘江西’}}}
User{sex=0, username=‘小明’, address=Address{detail=‘上海浦东’, province=Province{name=‘上海’}}}