如何实现对象克隆?

有两种方式:

1). 实现 Cloneable 接口并重写 Object 类中的 clone()方法;

2). 实现 Serializable 接口,通过对象的序列化和反序列化实现克隆,可以实现真

正的深度克隆,代码如下。

import java.io.ByteArrayInputStream;

import java.io.ByteArrayOutputStream;

import java.io.ObjectInputStream;

import java.io.ObjectOutputStream;

import java.io.Serializable;

public class MyUtil {

private MyUtil() {

throw new AssertionError();

}

@SuppressWarnings("unchecked")

public static <T extends Serializable> T clone(T obj) throws

Exception {

ByteArrayOutputStream bout = new ByteArrayOutputStream();

ObjectOutputStream oos = new ObjectOutputStream(bout);

oos.writeObject(obj);

ByteArrayInputStream bin = new

ByteArrayInputStream(bout.toByteArray());

ObjectInputStream ois = new ObjectInputStream(bin);

return (T) ois.readObject();

// 说明:调用 ByteArrayInputStream 或 ByteArrayOutputStream

对象的 close 方法没有任何意义

// 这两个基于内存的流只要垃圾回收器清理对象就能够释放资源,这

一点不同于对外部资源(如文件流)的释放

}

}

下面是测试代码:

import java.io.Serializable;

/**

* 人类

* @author 骆昊

*

*/

class Person implements Serializable {

private static final long serialVersionUID = -9102017020286042305L;

private String name;

// 姓名

private int age;

// 年龄

private Car car;

// 座驾

public Person(String name, int age, Car car) {

this.name = name;

this.age = age;

this.car = car;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public int getAge() {

return age;

}

public void setAge(int age) {

this.age = age;

}

public Car getCar() {

return car;

}

public void setCar(Car car) {

this.car = car;

}

@Override

public String toString() {

return "Person [name=" + name + ", age=" + age + ", car=" +

car + "]";

}

}

/**

* 小汽车类

* @author 骆昊

*

*/

class Car implements Serializable {

private static final long serialVersionUID = -5713945027627603702L;

private String brand;

// 品牌

private int maxSpeed;

// 最高时速

public Car(String brand, int maxSpeed) {this.brand = brand;

this.maxSpeed = maxSpeed;

}

public String getBrand() {

return brand;

}

public void setBrand(String brand) {

this.brand = brand;

}

public int getMaxSpeed() {

return maxSpeed;

}

public void setMaxSpeed(int maxSpeed) {

this.maxSpeed = maxSpeed;

}

@Override

public String toString() {

return "Car [brand=" + brand + ", maxSpeed=" + maxSpeed +

"]";

}

}

class CloneTest {

public static void main(String[] args) {

try {

Person p1 = new Person("Hao LUO", 33, new Car("Benz",

300));

Person p2 = MyUtil.clone(p1);

// 深度克隆

p2.getCar().setBrand("BYD");

// 修改克隆的 Person 对象 p2 关联的汽车对象的品牌属性

// 原来的 Person 对象 p1 关联的汽车不会受到任何影响

// 因为在克隆 Person 对象时其关联的汽车对象也被克隆了

System.out.println(p1);

} catch (Exception e) {

e.printStackTrace();

}

}

}

注意:基于序列化和反序列化实现的克隆不仅仅是深度克隆,更重要的是通过泛

型限定,可以检查出要克隆的对象是否支持序列化,这项检查是编译器完成的,

不是在运行时抛出异常,这种是方案明显优于使用 Object 类的 clone 方法克隆对

象。让问题在编译的时候暴露出来总是好过把问题留到运行时。

posted @ 2020-06-05 21:17  咔啡  阅读(1223)  评论(0编辑  收藏  举报