浅谈java的浅复制与深复制
1 前言
在java中浅复制也就是默认的对象的clone(),也就是object对象的clone()方法,这个方法可以对对象进行克隆也就是复制,会分配出一个与源对象空间大小一样的对象。
这里的克隆并不是引用对象
举个例子:
Test a= new Test();
Test b= a;
System.out.println(a==b);
输出结果 true
打印的结果为true
也就是说a 和 b 的内存地址是一样的,但是b没有新创建出一个对象。这个只能算做对象的引用,只是将内存地址指向了变量b而已。
2 浅复制与深复制
2.1 浅复制
浅复制就是按位拷贝对象,会创建出一个对象,如果对象的属性是基本属性值,复制的就是基本引用的值,如果是引用型就复制引用值。
2.1.1基本类型的拷贝
要实现浅复制必须实现Cloneable接口 重写clone()方法
public class Person implements Cloneable{
String name ;
String sex ;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return (Person) super.clone();
}
}
输出的内存地址是不同的:
com.udeam.udeam.clone1.Person@1b6d3586
com.udeam.udeam.clone1.Person@4554617c
实现了对象对象的复制与拷贝。
引用类型的拷贝
新建User类,并且在person类中添加一个 User 类 的引用
public class User {
String gread;
public String getGread() {
return gread;
}
public void setGread(String gread) {
this.gread = gread;
}
}
Person 类
package com.udeam.udeam.clone1;
public class Person implements Cloneable{
String name ;
String sex ;
User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return (Person) super.clone();
}
}
Test
User user = new User();
user.setGread("1班");
Person person1 = new Person();
person1.setName("zs");
person1.setSex("男");
person1.setUser(user);
//克隆
Person person2 = (Person) person1.clone();
person2.setUser(new User());
System.out.println(person1);
System.out.println(person2);
输出
com.udeam.udeam.clone1.Person@1b6d3586—com.udeam.udeam.clone1.User@4554617c
com.udeam.udeam.clone1.Person@74a14482—com.udeam.udeam.clone1.User@4554617c
浅复制中的属性是引用型时候,浅复制的对象内存地址不一致,达到创建对象的目的
但是对象里面的引用型属性的内存地址是相同的,并没有创建对象,只是对源对象的内存地址的引用。
2.2 深复制
浅复制中属性是引用型的对象时候,浅复制不能创建对象,只是对对象的引用。
如何来彻底的将浅复制中的引用型也进行复制,从而创建出一个兑现呢!
同样的实现Clonable接口,对其重写clone方法。在pserson 的clone()方法中赋值新的引用地址
@Override
protected Object clone() throws CloneNotSupportedException {
Person person = (Person) super.clone();
//对引用的对象user对象的复制
person.user = (User) user.clone();
return person;
}
然后我们再来测试:
com.udeam.udeam.clone1.Person@1b6d3586—com.udeam.udeam.clone1.User@4554617c
com.udeam.udeam.clone1.Person@74a14482—com.udeam.udeam.clone1.User@1540e19d
深复制将浅复制中的引用属性的引用地址指向新创建出来的对象的地址,而不是原来引用的地址,这就是所谓的深复制了。
无论是浅复制还是深复制被复制出来的对象与源对象的属性值一致!是因为第一次创建对象的时候new 出来的对象通过属性值进行初始化的原因,然后又被克隆出一份,原属性的值相继也会被克隆!
再进行赋值就会改变。