热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

对象拷贝(五)

对象拷贝61.为什么要使用克隆?想对一个对象进行处理,又想保留原有的数据进行接下来的操作,就需要克隆了,Java语言中克

对象拷贝

61. 为什么要使用克隆?

想对一个对象进行处理,又想保留原有的数据进行接下来的操作,就需要克隆了,Java语言中克隆针对的是类的实例。

62. 如何实现对象克隆?

有两种方式:

实现Cloneable接口并重写Object类中的clone()方法;
实现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();}&#64;SuppressWarnings("unchecked")public static <T extends Serializable> T clone(T obj) throws Exception {ByteArrayOutputStream bout &#61; new ByteArrayOutputStream();ObjectOutputStream oos &#61; new ObjectOutputStream(bout);oos.writeObject(obj);ByteArrayInputStream bin &#61; new ByteArrayInputStream(bout.toByteArray());ObjectInputStream ois &#61; new ObjectInputStream(bin);return (T) ois.readObject();// 说明&#xff1a;调用ByteArrayInputStream或ByteArrayOutputStream对象的close方法没有任何意义// 这两个基于内存的流只要垃圾回收器清理对象就能够释放资源&#xff0c;这一点不同于对外部资源&#xff08;如文件流&#xff09;的释放}
}

下面是测试代码&#xff1a;

import java.io.Serializable;/*** 人类* &#64;author nnngu**/
class Person implements Serializable {private static final long serialVersionUID &#61; -9102017020286042305L;private String name; // 姓名private int age; // 年龄private Car car; // 座驾public Person(String name, int age, Car car) {this.name &#61; name;this.age &#61; age;this.car &#61; car;}public String getName() {return name;}public void setName(String name) {this.name &#61; name;}public int getAge() {return age;}public void setAge(int age) {this.age &#61; age;}public Car getCar() {return car;}public void setCar(Car car) {this.car &#61; car;}&#64;Overridepublic String toString() {return "Person [name&#61;" &#43; name &#43; ", age&#61;" &#43; age &#43; ", car&#61;" &#43; car &#43; "]";}}

/*** 小汽车类* &#64;author nnngu**/
class Car implements Serializable {private static final long serialVersionUID &#61; -5713945027627603702L;private String brand; // 品牌private int maxSpeed; // 最高时速public Car(String brand, int maxSpeed) {this.brand &#61; brand;this.maxSpeed &#61; maxSpeed;}public String getBrand() {return brand;}public void setBrand(String brand) {this.brand &#61; brand;}public int getMaxSpeed() {return maxSpeed;}public void setMaxSpeed(int maxSpeed) {this.maxSpeed &#61; maxSpeed;}&#64;Overridepublic String toString() {return "Car [brand&#61;" &#43; brand &#43; ", maxSpeed&#61;" &#43; maxSpeed &#43; "]";}}

class CloneTest {public static void main(String[] args) {try {Person p1 &#61; new Person("郭靖", 33, new Car("Benz", 300));Person p2 &#61; MyUtil.clone(p1); // 深度克隆p2.getCar().setBrand("BYD");// 修改克隆的Person对象p2关联的汽车对象的品牌属性// 原来的Person对象p1关联的汽车不会受到任何影响// 因为在克隆Person对象时其关联的汽车对象也被克隆了System.out.println(p1);} catch (Exception e) {e.printStackTrace();}}
}

注意&#xff1a;基于序列化和反序列化实现的克隆不仅仅是深度克隆&#xff0c;更重要的是通过泛型限定&#xff0c;可以检查出要克隆的对象是否支持序列化&#xff0c;这项检查是编译器完成的&#xff0c;不是在运行时抛出异常&#xff0c;这种是方案明显优于使用Object类的clone方法克隆对象。让问题在编译的时候暴露出来总是好过把问题留到运行时。

63. 深拷贝和浅拷贝区别是什么&#xff1f;

浅拷贝只是复制了对象的引用地址&#xff0c;两个对象指向同一个内存地址&#xff0c;所以修改其中任意的值&#xff0c;另一个值都会随之变化&#xff0c;这就是浅拷贝&#xff08;例&#xff1a;assign()&#xff09;
深拷贝是将对象及值复制过来&#xff0c;两个对象修改其中任意的值另一个值不会改变&#xff0c;这就是深拷贝&#xff08;例&#xff1a;JSON.parse()和JSON.stringify()&#xff0c;但是此方法无法复制函数类型&#xff09;


原文地址&#xff1a;https://mp.weixin.qq.com/s/0KM4e3_zPczHh2TH2r_ncA



推荐阅读
author-avatar
小P美容2000
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有