java对象深克隆_Java对象深克隆的两种方式

# clone的条件

如果你想clone一个对象,就必须满足两个条件:

1. 你必须实现Cloneable接口(用于标识该对象可被clone,空接口)

2. 必须覆盖Object的clone方法

clone分为浅克隆和深克隆。Object对象的clone方法是浅克隆,即待克隆的对象若存在对象实例域,则仅仅clone其引用。深克隆即clone对象本体。

# 实现深克隆的方式

1. 先使用待克隆对象的clone方法,再调用对象实例域的clone方法并将结果覆盖引用类型。(待克隆对象和其对象实例域必须实现Cloneable接口并覆盖clone方法)

2. 使用对象序列化clone。(克隆对象和其对象实例域必须实现Serializable接口)

```

import java.io.ByteArrayInputStream;

import java.io.ByteArrayOutputStream;

import java.io.IOException;

import java.io.ObjectInputStream;

import java.io.ObjectOutputStream;

import java.io.Serializable;

/**

* ------------对象克隆测试---------------

*


* Object的clone方法是浅克隆,即待克隆的类实例域中存在对象时,仅仅clone其引用。

* 一个对象想要被克隆要满足两个条件:

* 1. 实现Cloneable接口,虽然是空接口,但表明该对象可以被clone

* 2. 覆盖Object的clone方法

*

* 深克隆的方式:

* 1. 使用实例域对象的clone方法clone自身。对于待克隆对象A的对象实例域B也实现Cloneable接口,并覆盖clone方法。

* 先调用A的clone方法clone自身,再调用B的clone方法克隆它自身并将该值覆盖A

* 对象的B实例域。

* 2. 使用序列化来clone对象A中的对象实例域。但是这种方式代价太高,因为序列化很慢并且不安全。

*

* @author xl

*

*/

public class ObjectClone {

public static void main(String[] args) {

Person p1 = new Person("Alice", true, (byte)12, new Student("001"));

System.out.println(p1);

try {

Person p2 = (Person) p1.clone();

System.out.println(p2);

} catch (CloneNotSupportedException e) {

e.printStackTrace();

}

}

}

class Person implements Cloneable, Serializable {

/**

*

*/

private static final long serialVersionUID = -5773931460922468711L;

protected String name;

boolean sex;

byte age;

Student s;

public Person(String name, boolean sex, byte age, Student s) {

super();

this.name = name;

this.sex = sex;

this.age = age;

this.s = s;

}

深克隆1:调用对象实例域的clone方法。待克隆对象和其对象字段必须实现Cloneable接口

//@Override

//protected Object clone() throws CloneNotSupportedException {

//Person person = (Person)super.clone();

//person.s = (Student) this.s.clone();

//return person;

//}

//深克隆2:使用对象序列clone。待克隆对象的对象字段必须实现Serializable接口

@Override

protected Object clone() throws CloneNotSupportedException {

Person person = null;

try (

ByteArrayOutputStream baos = new ByteArrayOutputStream();

ObjectOutputStream oos = new ObjectOutputStream(baos);

) {

//将待克隆对象序列化

oos.writeObject(this);

try (ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()));) {

//反序列化待克隆对象并在内存中重建

person = (Person)ois.readObject();

} catch (ClassNotFoundException e) {

e.printStackTrace();

}

} catch (IOException e) {

e.printStackTrace();

}

return person;

}

@Override

public String toString() {

return "Person [name=" + name + ", sex=" + sex + ", age=" + age + ", s=" + s + "]";

}

}

class Student implements Cloneable, Serializable {

/**

*

*/

private static final long serialVersionUID = 2741427318104578724L;

String id = "001";

public Student(String id) {

this.id = id;

}

@Override

protected Object clone() throws CloneNotSupportedException {

return super.clone();

}

}

```

>环境:

java version "1.8.0_111"

Java(TM) SE Runtime Environment (build 1.8.0_111-b14)

Java HotSpot(TM) Client VM (build 25.111-b14, mixed mode)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值