在 Java 的学习过程,很多人在拷贝的时候,都习惯用 clone 方法直接拷贝,但有时候总会出现一些问题,看我举例:
先定义Person类存储个人信息:
class Person implements Cloneable{
//姓名
String name;
//电话
String phone;
//性别
String sex;
public Person(String name, String phone, String sex) {
super();
this.name = name;
this.phone = phone;
this.sex = sex;
}
@Override
public String toString() {
return "Person [name=" + name + ", phone=" + phone + ", sex=" + sex + "]";
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
在定义用户类存储账号密码和个人信息:
class User implements Cloneable{
//用户id
int userid;
//用户密码
String password;
//用户信息
Person person;
public User(int userid, String password, Person person) {
super();
this.userid = userid;
this.password = password;
this.person = person;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
public String toString() {
return "User [userid=" + userid + ", password=" + password + ", person=" + person + "]";
}
}
现在我们创建一个User类进行拷贝:
public class Demo {
public static void main(String[] args) throws CloneNotSupportedException {
Person person = new Person("yin", "1008611", "女");
User user1 = new User(1, "123123", person);
//对 user1 进行克隆
User user2 = (User) user1.clone();
//输出信息
System.out.println(user1);
System.out.println(user2);
//对账号密码进行修改
user2.userid = 2;
user2.password = "112233";
//输出信息
System.out.println(user1);
System.out.println(user2);
//对 user1 用户信息进行修改
user1.person.name = "xu";
user1.person.phone = "106688";
user1.person.sex = "男";
//输出信息
System.out.println(user1);
System.out.println(user2);
}
}
执行结果:
User [userid=1, password=123123, person=Person [name=yin, phone=1008611, sex=女]]
User [userid=1, password=123123, person=Person [name=yin, phone=1008611, sex=女]]
User [userid=1, password=123123, person=Person [name=yin, phone=1008611, sex=女]]
User [userid=2, password=112233, person=Person [name=yin, phone=1008611, sex=女]]
User [userid=1, password=123123, person=Person [name=xu, phone=106688, sex=男]]
User [userid=2, password=112233, person=Person [name=xu, phone=106688, sex=男]]
从执行结果可以看出,虽然我们拷贝了 user1,但当我们对 user1 中的 person 进行修改时,user2 的 person 信息也会跟着改变,像这种只拷贝了类的属性的方式,就称作 浅拷贝,因为我们只拷贝了对象本身,却没有拷贝对象包含的引用指向的对象,而 深拷贝 则是会对这些指向的对象一起拷贝。
看我对 User 类的 clone方法做个修改:
@Override
protected Object clone() throws CloneNotSupportedException {
User user = (User) super.clone();
user.person = (Person) person.clone();
return user;
}
再看执行结果:
User [userid=1, password=123123, person=Person [name=yin, phone=1008611, sex=女]]
User [userid=1, password=123123, person=Person [name=yin, phone=1008611, sex=女]]
User [userid=1, password=123123, person=Person [name=yin, phone=1008611, sex=女]]
User [userid=2, password=112233, person=Person [name=yin, phone=1008611, sex=女]]
User [userid=1, password=123123, person=Person [name=xu, phone=106688, sex=男]]
User [userid=2, password=112233, person=Person [name=yin, phone=1008611, sex=女]]
这样 user2 的个人信息就不会随 user1 个人信息改变而改变了,这种拷贝方式就是 深拷贝。
注意:深拷贝 在遇到对象层级比较的大的对象时,性能消耗会很大,所以如果有比 深拷贝 更好的方式就采用更好的方式。