资讯专栏INFORMATION COLUMN

Java实现对象克隆的方法

zhoutk / 2701人阅读

摘要:优点简单易实现缺点无法真正克隆对象深克隆实现通过递归克隆实现代码输出通过序列化实现代码输出结果分析采用深克隆能有效隔离源对象与克隆对象的联系。

本文首发于cartoon的博客     
转载请注明出处:https://cartoonyu.github.io/cartoon-blog/post/java/java%E5%AE%9E%E7%8E%B0%E5%85%8B%E9%9A%86%E7%9A%84%E6%96%B9%E6%B3%95/

前言

这也是昨天的面试题。

当时只说了深拷贝以及浅拷贝,面试官问了两遍还有吗,我很肯定的说就这两种了,面试结束之后查了一下,啪啪打脸。

正文

JAVA实现克隆有两种形式

浅克隆

深克隆

浅克隆与深克隆的区别

JAVA将数据类型分为基本数据类型以及引用数据类型,我认为浅克隆与深克隆的区别主要在于对引用类型的成员属性的操作。深度克隆应该递归克隆引用类型的成员属性。

浅克隆实现

实现Cloneable接口

重写clone方法,调用父类的clone方法

代码

public class Text implements Cloneable{
 ​
  private int age;
 ​
  private Name name;
 ​
  public int getAge() {
  return age;
  }
 ​
  public void setAge(int age) {
  this.age = age;
  }
 ​
  public Name getName() {
  return name;
  }
 ​
  public void setName(Name name) {
  this.name = name;
  }
 ​
  @Override
  protected Object clone(){
  try {
  return super.clone();
  } catch (CloneNotSupportedException e) {
  e.printStackTrace();
  }
  return null;
  }
 }
 ​
 class Name{
  private String name;
 ​
  public String getName() {
  return name;
  }
 ​
  public void setName(String name) {
  this.name = name;
  }
 }
 ​
 public class Main {
 ​
  public static void main(String[] args){
  Name name1=new Name();
  name1.setName("name1");
  Text t1=new Text();
  t1.setAge(12);
  t1.setName(name1);
  Text t2=(Text) t1.clone();
  System.out.println(t2.getName().getName());
  name1.setName("name2");
  System.out.println(t2.getName().getName());
 ​
  }
 ​
 }

输出

name1
name2

结果分析

因为只是直接调用父类的clone方法,没有对成员属性进行处理,所以在修改t1属性name的值时,t2属性name的值也会随之改变。

优点

简单易实现

缺点

无法真正克隆对象

深克隆实现
通过递归克隆实现

代码

 public class Text implements Cloneable{
 ​
  private int age;
 ​
  private Name name;
 ​
  public int getAge() {
  return age;
  }
 ​
  public void setAge(int age) {
  this.age = age;
  }
 ​
  public Name getName() {
  return name;
  }
 ​
  public void setName(Name name) {
  this.name = name;
  }
 ​
  @Override
  protected Object clone(){
  Text text=null;
  try {
  text=(Text) super.clone();
  } catch (CloneNotSupportedException e) {
  e.printStackTrace();
  }
  text.setName((Name) text.getName().clone());
  return text;
  }
 }
 ​
 class Name implements Cloneable{
  private String name;
 ​
  public String getName() {
  return name;
  }
 ​
  public void setName(String name) {
  this.name = name;
  }
 ​
  @Override
  protected Object clone() {
  try {
  return super.clone();
  } catch (CloneNotSupportedException e) {
  e.printStackTrace();
  }
  return null;
  }
 }

输出

name1
name1
通过序列化实现

代码

 public class Text implements Serializable{
 ​
  private static final long serialVersionUID = 8723901148964L;
 ​
  private int age;
 ​
  private Name name;
 ​
  public int getAge() {
  return age;
  }
 ​
  public void setAge(int age) {
  this.age = age;
  }
 ​
  public Name getName() {
  return name;
  }
 ​
  public void setName(Name name) {
  this.name = name;
  }
 ​
  public Object myClone(){
  Text text=null;
  ByteArrayOutputStream bos=new ByteArrayOutputStream();
  try {
  ObjectOutputStream oos=new ObjectOutputStream(bos);
  oos.writeObject(this);
  ByteArrayInputStream bis=new ByteArrayInputStream(bos.toByteArray());
  ObjectInputStream ois=new ObjectInputStream(bis);
  text=(Text)ois.readObject();
  } catch (IOException e) {
  e.printStackTrace();
  } catch (ClassNotFoundException e) {
  e.printStackTrace();
  }
  return text;
  }
 }
 ​
 class Name implements Serializable {
 ​
  private static final long serialVersionUID = 872390113109L;
 ​
  private String name;
 ​
  public String getName() {
  return name;
  }
 ​
  public void setName(String name) {
  this.name = name;
  }
 ​
  @Override
  public String toString() {
  return name;
  }
 }

输出

 name1
 name1

结果分析

采用深克隆能有效隔离源对象与克隆对象的联系。

从实现过程来说,递归克隆存在克隆过程多且复杂的缺点,所以建议采用序列化的方式进行

深克隆。

总结

JAVA对象克隆共有两种形式,三种方法

浅克隆

调用clone方法

深克隆

递归调用clone方法

序列化对象

三种方法之间互有优缺点,具体采用要根据实际情况。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/77829.html

相关文章

  • Java 作者谈克隆方法实现

    摘要:不合规的代码示例合规解决方案参阅复制构造函数与克隆也可以参阅应该实现克隆覆盖的类应为并调用下面为引文翻译谈设计与作者的对话,作者首次在上发表,年月日复制构造函数与克隆在你的书中,你建议使用复制构造函数而不是实现和编写。 今天在用 sonar 审核代码, 偶然看到下面的提示:showImg(https://segmentfault.com/img/bVbqioZ?w=858&h=116)...

    gaomysion 评论0 收藏0
  • Java对象克隆了解标识接口

    摘要:主要内容清楚对象克隆的操作结构巩固接口的作用具体内容对象克隆对象克隆指的就是对象的复制操作,在类里面提供有一个专门克隆的方法。此方法上抛出一个异常,如果要使用对象克隆的类没有实现接口,那么就会抛出此异常。 主要内容 清楚对象克隆的操作结构巩固接口的作用具体内容 对象克隆 对象克隆指的就是对象的复制操作,在Object类里面提供有一个专门克隆的方法。 对象克隆:protected Obj...

    DesGemini 评论0 收藏0
  • 深入理解原型模式 ——通过复制生成实例

    摘要:定义给出的原型模式定义如下使用原型实例指定将要创建的对象类型,通过复制这个实例创建新的对象。具体原型类角色负责实现复制现有实例并生成新实例的方法。 Java面试通关手册(Java学习指南,欢迎Star,会一直完善下去,欢迎建议和指导):https://github.com/Snailclimb/Java_Guide 系列文章回顾: 设计模式专栏深入理解单例模式深入理解工厂模式 深入理解...

    Pocher 评论0 收藏0
  • Java问题汇总,持续更新到GitHub

    摘要:目录介绍问题汇总具体问题好消息博客笔记大汇总年月到至今,包括基础及深入知识点,技术博客,学习笔记等等,还包括平时开发中遇到的汇总,当然也在工作之余收集了大量的面试题,长期更新维护并且修正,持续完善开源的文件是格式的同时也开源了生活博客,从年 目录介绍 00.Java问题汇总 01.具体问题 好消息 博客笔记大汇总【16年3月到至今】,包括Java基础及深入知识点,Android技...

    beita 评论0 收藏0
  • 从clone方法到复制构造函数

    摘要:有一些设计缺陷,其中最大的一个是接口没有方法。这基本上就是你用复制构造函数做的事情。复制构造方法有几个优点,我在本书中有讨论。的方法是非常棘手的。它创建一个对象而不调用构造函数。无法保证它保留构造函数建立的不变量。 前言 在Java API中,可以通过实现Cloneable接口并重写clone方法实现克隆,但Java设计者否定了使用clone创建新对象的方法. 1. clone方法实现...

    孙吉亮 评论0 收藏0

发表评论

0条评论

zhoutk

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<