对象的浅拷贝

来源:互联网 发布:淘宝手机充值退款 编辑:程序博客网 时间:2024/05/07 14:42

一个类实现Cloneable接口,那么它就具有了被拷贝的能力,如覆写clone方法之后就完全具备拷贝的能力。因为拷贝是在内存中进行的,所以在性能上比new生成对象要快很多,那么,拷贝是完全拷贝吗?下面看一个例子。

public class Person implements Cloneable{

//姓名

private String name;

//父亲

private Person father;

public Person(String name) {

super();

this.name = name;

}

public Person(String name, Person father) {

super();

this.name = name;

this.father = father;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public Person getFather() {

return father;

}

public void setFather(Person father) {

this.father = father;

}

//实现拷贝

@Override

public Person clone(){

Person p=null;

try {

p=(Person)super.clone();

} catch (CloneNotSupportedException e) {

e.printStackTrace();

}

return p;

}

在这边我们定义了一个Person类,现在要描述一个场景,一个父亲有两个儿子,小儿子通过拷贝大儿子对象来生成,下面看下测试的方法。

对象的浅拷贝

测试方法

这边可以看到输出的没有问题,那么突然有一天,父亲想让大儿子去认一个义父,也就是图上注释掉的代码,将代码写到小儿子命名完后。那么结果会如何呢?

对象的浅拷贝

换父亲

可以看到小儿子的父亲也变了!这是为什么呢?因为拷贝时super.clone()方法调用的是Object的方法,就是这个方法的原因,它是一种浅拷贝的方式。也就是说不是把对象的所有属性拷贝一份,而是有选择性的拷贝。拷贝的规则如下:

  1. 基本类型

    如果变量是基本类型,则拷贝值。

  2. 对象

    如果对象是一个实例遍历,则拷贝地址引用,也就是说拷贝出来新的对象与原有的对象共享该实例变量。

  3. String字符串

    这个比较特殊,拷贝的是一个地址,是个引用,但是在修改的时候,他会在字符串池中重新生成新的字符串,原有的字符串对象保持不变。

所以也就是说,小儿子的对象是通过拷贝大儿子产生的,父亲是同一个,也就是同一个对象。于是修改了大儿子的父亲值,小儿子也跟着修改了。同理改小儿子的父亲也是一样,大儿子也会跟着修改。

那么怎么改呢?就是在拷贝的时候生成新的对象就可以了。

public Person clone(){

Person p=null;

try {

p=(Person)super.clone();

p.setFather(new Person(p.getFather().getName()));

} catch (CloneNotSupportedException e) {

e.printStackTrace();

}

return p;

}

0 0
原创粉丝点击