java deepcloneobject,Java Object之clone()方法

Object中的clone方法定义如下:

protected native Object clone() throws CloneNotSupportedException;

定义一个可克隆的对象,一般的步骤如下:

implements Cloneable;

override clone()

Example

//Person及其子类都有了克隆能力

class Person implements Cloneable {

private int age;

private String name;

Person(int age, String name){

this.age = age;

this.name = name;

}

public String getName() {

return name;

}

@Override

public Object clone() {

try {

//实际调用了Object的clone()

return super.clone();

} catch (CloneNotSupportedException e){

e.printStackTrace();

return null;

}

}

@Override

public String toString() {

return "Person{" +

"age=" + age +

", name='" + name.hashCode() + '\'' +

'}';

}

}

如果调用Person personOfClone = person.clone(),实际上进行的是 shallow copy,即person和personOfClone中的name引用的是同一块内存地址。对personOfClone的修改可能会影响到person。那么如何进行 deep copy?若要实现 deep copy,则必须对对象内部的引用进行clone(前提是这些引用是可克隆的)直到所有的引用都进行了clone。

默认浅克隆是合理的,因为不能确定所有的引用都是可以克隆的。

通过序列化实现 deep copy

Example

public class Compete {

public static final int SIZE = 25000;

public static void main(String[] args) throws Exception {

Thing2[] a = new Thing2[SIZE];

for (int i = 0; i < a.length; i++)

a[i] = new Thing2();

long t1 = System.currentTimeMillis();

ByteArrayOutputStream buf = new ByteArrayOutputStream();

ObjectOutputStream o = new ObjectOutputStream(buf);

for (int i = 0; i < a.length; i++)

o.writeObject(a[i]);

// Now get copies:

ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(buf.toByteArray()));

Thing2[] c = new Thing2[SIZE];

for (int i = 0; i < c.length; i++)

//这里实际上已经进行了copy

c[i] = (Thing2) in.readObject();

long t2 = System.currentTimeMillis();

System.out.println("Duplication via serialization: " +

(t2 - t1) + " Milliseconds");

//clone

Thing4[] b = new Thing4[SIZE];

for (int i = 0; i < b.length; i++)

b[i] = new Thing4();

t1 = System.currentTimeMillis();

Thing4[] d = new Thing4[SIZE];

for (int i = 0; i < d.length; i++)

d[i] = (Thing4) b[i].clone();

t2 = System.currentTimeMillis();

System.out.println("Duplication via cloning: " +

(t2 - t1) + " Milliseconds");

}

static class Thing1 implements Serializable {

}

static class Thing2 implements Serializable {

Thing1 o1 = new Thing1();

}

static class Thing3 implements Cloneable {

public Object clone() {

Object o = null;

try {

o = super.clone();

} catch (CloneNotSupportedException e) {

System.err.println("Thing3 can't clone");

}

return o;

}

}

static class Thing4 implements Cloneable {

private Thing3 o3 = new Thing3();

public Object clone() {

Thing4 o = null;

try {

o = (Thing4) super.clone();

} catch (CloneNotSupportedException e) {

System.err.println("Thing4 can't clone");

}

// Clone the field, too:

o.o3 = (Thing3) o3.clone();

return o;

}

}

}

运行后发现,直接clone的速度要远快于序列化

控制克隆能力

上述例子中,一个对象首先要实现Cloneable对象,然后覆写clone()才能具有克隆能力,那么为何这样设计?

假如Object.clone()是public的

实际上,java起初是这样设计的,Object中添加了public 的clone(),那么任何对象都可以克隆了,但是如果每个对象都是可以随意克隆的,就会出现安全性问题(你不一定愿意别人克隆你的对象);今天看到的样子,是做了许多修补之后的版本:Object 中的 clone()被声明为 protected,你必须重载它、实现 Cloneable 接口、并做异常处理。

假如Object.clone()是private的

这样的话,子类都不能使用Object中的native方法了。

为何调用Object.clone()

调用Object.clone()时实际会发生什么,致使你重载clone()时必须要调用super.clone() 呢? 原因大概如下:

Object 类的 clone()方法负责创建正确容量的存储空间,并将属性值由原对象复制到新对象的存储空间中;

此方法是native的,效率很高;

可以防止不能克隆的对象进行克隆;此方法会在运行期间通过Cloneable对象判断对象是否可以克隆,如果不能克隆,则会抛异常。所以,若子类的方法没有调用Object.clone(),那么实际上是不用实现Cloneable接口的。但为了使具备克隆能力的对象保持一致性,可克隆的对象应该都实现该接口。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值