Java实现克隆的三种方式实例总结

 更新时间:2018年08月23日 09:40:33   作者:疯狂1024  
这篇文章主要介绍了Java实现克隆的三种方式,结合实例形式总结分析了java浅复制、深复制以及使用serializable实现深复制的相关操作技巧,需要的朋友可以参考下

本文实例讲述了Java实现克隆的三种方式。分享给大家供大家参考,具体如下:

1、浅复制(浅克隆)这种浅复制,其实也就是把被复制的这个对象的一些变量值拿过来了。最后生成student2还是一个新的对象。

public class CloneTest1
{
  public static void main(String[] args) throws Exception
  {
    Student1 student = new Student1();
    student.setAge(24);
    student.setName("niesong");
    Student1 student2 = (Student1)student.clone();
    //这个是调用下面的那个方法,然后把这个这个对象Clone到student
    System.out.println("Age:" + student2.getAge() + " " + "Name:" + student2.getName());
    System.out.println("---------------------");
    student2.setAge(23);
    //克隆后得到的是一个新的对象,所以重新写的是student2这个对象的值
    System.out.println(student.getAge());
    System.out.println(student2.getAge());
  }
}
//克隆的对象必须实现Cloneable这个接口,而且需要重写clone方法
class Student1 implements Cloneable
{
  private int age;
  //定义为private说明这个成员变量只能被被当前类中访问,如果外部需要获得,那么就只能通过getAge方法进行获取
  private String name;
  public int getAge()
  {
    return age;
  }
  public void setAge(int age)
  {
    this.age = age;
  }
  public String getName()
  {
    return name;
  }
  public void setName(String name)
  {
    this.name = name;
  }
  @Override
  public Object clone() throws CloneNotSupportedException
  {
    Object object = super.clone();
    return object;
  }
}

运行结果:

2、深复制(情况1使用的是在克隆的时候手动进行深克隆)

public class CloneTest2
{
  public static void main(String[] args) throws Exception
  {
    Teacher teacher = new Teacher();
    teacher.setAge(40);
    teacher.setName("teacher zhang");
    Student2 student2 = new Student2();
    student2.setAge(14);
    student2.setName("lisi");
    student2.setTeacher(teacher);
    Student2 student3 = (Student2)student2.clone();
    //这里是深复制,所以这时候Student2中的teacher就是teacher这个对象的一个复制,就和student3是student2的一个复制
    //所以下面teacher.setName只是对他原来的这个对象更改,但是复制的那个并没有更改
    System.out.println(student3.getAge());
    System.out.println(student3.getName());
    System.out.println(student3.getTeacher().getAge());
    teacher.setName("teacher niesong");//不会又任何影响
    System.out.println(student3.getTeacher().getName());
  }
}
class Student2 implements Cloneable
{
  private int age;
  private String name;
  private Teacher teacher;
  public int getAge()
  {
    return age;
  }
  public void setAge(int age)
  {
    this.age = age;
  }
  public String getName()
  {
    return name;
  }
  public void setName(String name)
  {
    this.name = name;
  }
  public Teacher getTeacher()
  {
    return teacher;
  }
  public void setTeacher(Teacher teacher)
  {
    this.teacher = teacher;
  }
  @Override
  public Object clone() throws CloneNotSupportedException
  {
    //这一步返回的这个student2还只是一个浅克隆,
    Student2 student2 = (Student2)super.clone();
    //然后克隆的过程中获得这个克隆的student2,然后调用这个getTeacher这个方方法得到这个Teacher对象。然后实现克隆。在设置到这个student2中的Teacher。
    //这样实现了双层克隆使得那个teacher对象也得到了复制。
    student2.setTeacher((Teacher)student2.getTeacher().clone());
    //双层克隆使得那个teacher对象也得到了复制
    return student2;
  }
}
class Teacher implements Cloneable
{
  private int age;
  private String name;
  public int getAge()
  {
    return age;
  }
  public void setAge(int age)
  {
    this.age = age;
  }
  public String getName()
  {
    return name;
  }
  public void setName(String name)
  {
    this.name = name;
  }
  @Override
  public Object clone() throws CloneNotSupportedException
  {
    return super.clone();
  }
}

运行结果:

3、利用serializable实现深复制(这个是利用Serializable,利用序列化的方式来实现深复制(深克隆),在其中利用了Io流的方式将这个对象写到IO流里面,然后在从IO流里面读取,这样就实现了一个复制,然后实现序列化的这个会将引用的那个对象也一并进行深复制,这样就实现了这个机制,同时在IO里面读取数据的时候还使用了装饰者模式)

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class CloneTest3
{
  public static void main(String[] args) throws Exception
  {
    Teacher3 teacher3 = new Teacher3();
    teacher3.setAge(23);
    teacher3.setName("niesong");
    Student3 student3 = new Student3();
    student3.setAge(50);
    student3.setName("wutao");
    student3.setTeacher3(teacher3);
    Student3 ss = (Student3)student3.deepCopt();
    System.out.println(ss.getAge());
    System.out.println(ss.getName());
    System.out.println("---------------------");
    System.out.println(ss.getTeacher3().getAge());
    System.out.println(ss.getTeacher3().getName());
    System.out.println("-----------------------");
    ss.getTeacher3().setAge(7777);
    ss.getTeacher3().setName("hhhhh");
    System.out.println(teacher3.getAge());
    System.out.println(teacher3.getName());
    //虽然上面的已经改了,但是改的是那个复制对象后的那个里面的,然后那个原来的那个里面的并没有改,下面验证:::
    System.out.println("-----------------");
    System.out.println(ss.getTeacher3().getAge());
    System.out.println(ss.getTeacher3().getName());
  }
}
class Teacher3 implements Serializable
{
// 上面的那个警告可以直接消除,除了使用在设置中不显示这个警告,还可以使用下面的这两条语句中的任何一条语句
//  这个serialVersionUID为了让该类别Serializable向后兼容
//  private static final long serialVersionUID = 1L;
//  private static final long serialVersionUID = 8940196742313994740L;
  private int age;
  private String name;
  public int getAge()
  {
    return age;
  }
  public void setAge(int age)
  {
    this.age = age;
  }
  public String getName()
  {
    return name;
  }
  public void setName(String name)
  {
    this.name = name;
  }
}
class Student3 implements Serializable
{
  private static final long serialVersionUID = 1L;
  private int age;
  private String name;
  private Teacher3 teacher3;
  public int getAge()
  {
    return age;
  }
  public void setAge(int age)
  {
    this.age = age;
  }
  public String getName()
  {
    return name;
  }
  public void setName(String name)
  {
    this.name = name;
  }
  public Teacher3 getTeacher3()
  {
    return teacher3;
  }
  public void setTeacher3(Teacher3 teacher3)
  {
    this.teacher3 = teacher3;
  }
  //使得序列化student3的时候也会将teacher序列化
  public Object deepCopt()throws Exception
  {
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    ObjectOutputStream oos = new ObjectOutputStream(bos);
    oos.writeObject(this);
    //将当前这个对象写到一个输出流当中,,因为这个对象的类实现了Serializable这个接口,所以在这个类中
    //有一个引用,这个引用如果实现了序列化,那么这个也会写到这个输出流当中
    ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
    ObjectInputStream ois = new ObjectInputStream(bis);
    return ois.readObject();
    //这个就是将流中的东西读出类,读到一个对象流当中,这样就可以返回这两个对象的东西,实现深克隆
  }
}

运行结果:

更多java相关内容感兴趣的读者可查看本站专题:《Java面向对象程序设计入门与进阶教程》、《Java数据结构与算法教程》、《Java操作DOM节点技巧总结》、《Java文件与目录操作技巧汇总》和《Java缓存操作技巧汇总

希望本文所述对大家java程序设计有所帮助。

相关文章

  • Java令牌Token登录与退出的实现

    Java令牌Token登录与退出的实现

    这篇文章主要介绍了Java令牌Token登录与退出的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-05-05
  • Java处理异常2种机制关键字区别解析

    Java处理异常2种机制关键字区别解析

    这篇文章主要介绍了java处理异常2种机制关键字区别解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-01-01
  • Hikari连接池使用SpringBoot配置JMX监控实现

    Hikari连接池使用SpringBoot配置JMX监控实现

    Hikari是Spring Boot默认的数据库连接池。区别于C3P0直接通过连接池对象获取各项状态指标,Hikari需要通过JMX来获取。本文就详细的来介绍一下,感兴趣的可以了解一下
    2021-07-07
  • 浅谈java中的局部变量和全局变量

    浅谈java中的局部变量和全局变量

    这篇文章主要涉及了java中的局部变量和全局变量,就二者的含义、生存时间和创建位置作了介绍,需要的朋友可以参考下。
    2017-09-09
  • java Quartz定时器任务与Spring task定时的几种实现方法

    java Quartz定时器任务与Spring task定时的几种实现方法

    本篇文章主要介绍了java Quartz定时器任务与Spring task定时的几种实现方法的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
    2017-02-02
  • 了解Java多线程的可见性与有序性

    了解Java多线程的可见性与有序性

    这篇文章主要介绍了了解Java多线程的可见性与有序性,在Java内存模型中,允许编译器和处理器对指令进行重排序,但是重排序过程不会影响到单线程程序的执行,却会影响到多线程并发执行的正确性。,需要的朋友可以参考下
    2019-06-06
  • 详解IntelliJ IDEA创建spark项目的两种方式

    详解IntelliJ IDEA创建spark项目的两种方式

    这篇文章主要介绍了详解IntelliJ IDEA创建spark项目的两种方式,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-01-01
  • 使用XSD校验Mybatis的SqlMapper配置文件的方法(1)

    使用XSD校验Mybatis的SqlMapper配置文件的方法(1)

    这篇文章以前面对SqlSessionFactoryBean的重构为基础,简单的介绍了相关操作知识,然后在给大家分享使用XSD校验Mybatis的SqlMapper配置文件的方法,感兴趣的朋友参考下吧
    2016-11-11
  • zuul过滤器中转发请求头的解决方案

    zuul过滤器中转发请求头的解决方案

    这篇文章主要介绍了zuul过滤器中转发请求头的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • Maven项目部署到Jboss出现Failed to create a new SAX parser

    Maven项目部署到Jboss出现Failed to create a new SAX parser

    这篇文章主要为大家详细介绍了Maven项目部署到Jboss出现Failed to create a new SAX parser的解决方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-11-11

最新评论