java 对象的克隆(浅克隆和深克隆)

作者:沈君 时间:2021-06-27 20:43:20 

java 对象的克隆

一、对象的浅克隆

(1)需要克隆类需要重写Object类的clone方法,并且实现Cloneable接口(标识接口,无需实现任何方法)
(2)当需要克隆的对象中维护着另外一个引用对象,浅克隆不会克隆另外一个引用对下,而是直接复制维护的另外一个引用对象的地址。
(3)对象的浅克隆也不会调用到构造方法。

以下为对象的浅克隆的一个例子:


package com.clone;

import java.io.Serializable;

/**
* Description:
* 实现了Cloneable接口,并重写Object类的clone方法。
*
* @author lee
* */
public class CloneDemo1 implements Cloneable,Serializable{

//该克隆类封装的信息
 public int id;
 public String name;
 public Address address;

/**
  * Desciption:
  * 默认构造器
  *
  * */
 public CloneDemo1(){}

/**
  * Description:
  * 初始化id,name的构造器
  *
  * @param id id
  * @param name 名字
  * @param address 地址
  * */
 public CloneDemo1(int id, String name, Address address){
   this.id=id;
   this.name=name;
   this.address = address;
 }

/**
  * Descriptin:
  * 重写Object类的clone方法。
  * if the object's class does not support the Cloneable interface.
  * Subclasses that override the clone method can also throw this exception
  * to indicate that an instance cannot be cloned.
  *
  * @throws CloneNotSupportedException
  * */
 @Override
 public Object clone() throws CloneNotSupportedException{
   return super.clone();
 }

/**
  * Description:
  * 重写toString方法
  *
  * @return "id="+id+", name="+name
  * */
 @Override
 public String toString(){
   return "id="+id+", name="+name+", address:"+address.getAddress();
 }

/**
  * Description:
  * 主方法
  *
  * */
 public static void main(String[] args) throws CloneNotSupportedException{

CloneDemo1 c1 = new CloneDemo1(1,"c1",new Address("北京"));
   //c2 复制了c1的地址,并没有复制整个c1对象
   CloneDemo1 c2 = c1;
   //c3 对象的浅克隆,复制了整个对象
   CloneDemo1 c3 = (CloneDemo1)c1.clone();

//当对象c1改变其name或者id的时候,c2也会自动改变。
   //因为c2只是复制了c1的地址,并非复制了c1的整个对象。
   //相应的c3则不会随着c1改变而改变,意味着c3将c1整个对象克隆一份出来。

//当是,对象的浅克隆不会克隆被克隆对象当中的引用对象。
   //因此c1改变其中的Address的引用对象时,c2,c3也会跟着改变。
   c1.setName("cc");
   c1.address.setAddress("上海");
   System.out.println(c1+"\n"+c2+"\n"+c3);

}

public int getId() {
   return id;
 }

public void setId(int id) {
   this.id = id;
 }

public String getName() {
   return name;
 }

public void setName(String name) {
   this.name = name;
 }

}

/**
* Description:
* 一个封装着地址的类
*
* @author lee
* */
class Address implements Serializable{
 public String address;

/**
  * Description:
  * 默认构造器
  *
  * */
 public Address(){}

/**
  * Description:
  * 初试化address
  *
  * @param address 地址
  * */
 public Address(String address){
   this.address = address;
 }

//address的set和get方法
 public String getAddress() {
   return address;
 }

public void setAddress(String address) {
   this.address = address;
 }
}

二、对象的深克隆

就是利用对象的输入输出流把对象写到文件上,再读取对象的信息,这就是对象的深克隆。

由于对象的浅克隆不会克隆被克隆对象其中的引用对象,而是直接复制其地址。因此,要克隆被克隆对象当中的引用类型则需要对象的深克隆。

而对象的深克隆使用的的对象序列化输入输出。

代码如下:


package com.clone;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

/**
* Description:
* 实现对象的深克隆
*
* @author lee
* */
public class CloneDemo2 {

/**
  * Description:
  * 将对象输出到一个文件当中。
  *
  * @param c 需要被写到文件当中的对象。
  * */
 public static void writeObject(CloneDemo1 c){

ObjectOutputStream out = null;
   try{

//将对象输出在一个object.txt文件当中
     out = new ObjectOutputStream(new FileOutputStream("./object.txt"));
     out.writeObject(c);

}catch(IOException e){
     System.out.println("写入对象的时候发生了错误。");
     e.printStackTrace();
   }finally{

//关闭资源
     try{
       out.close();
     }catch(IOException e){
       e.printStackTrace();
     }
   }

}

/**
  * Description:
  * 从文件中读取出一个对象来,并返回。
  *
  * @return c 返回一个对象。
  * */
 public static CloneDemo1 readObject(){

CloneDemo1 c = null;
   ObjectInputStream input = null;
   try{
     //从object.txt文件中读取一个对象出来
     input = new ObjectInputStream(new FileInputStream("./object.txt"));
     c = (CloneDemo1)input.readObject();

}catch(IOException | ClassNotFoundException e){
     e.printStackTrace();
     System.out.println("读取对象的时候发生了错误。");
   }finally{
     //关闭资源
     try{
       input.close();
     }catch(IOException e){
       e.printStackTrace();
     }
   }
   return c;
 }
 /**
  * Description:
  * 主方法
  *
  * @throws CloneNotSupportedException
  * */
 public static void main(String[] args) throws CloneNotSupportedException {
   CloneDemo1 c1 = new CloneDemo1(1,"c1",new Address("北京"));
   //c2 对象的浅克隆
   CloneDemo1 c2 = (CloneDemo1)c1.clone();
   //c3对象的深克隆
   writeObject(c1);
   CloneDemo1 c3 = readObject();

//因为对象的深克隆同时也克隆了被克隆对象维护的另外一个对象
   //所以,当c1改变其当中的维护的另外一个对象的时候,c3不会随之改变。
   //而c2位浅克隆,其维护的另外一个对象只是复制了c1维护的对象的地址,因此会随着c1的改变而改变。
   c1.address.setAddress("上海");
   System.out.println(c1+"\n"+c2+"\n"+c3);

}

}

对象的序列化,是需要实现Serializable接口的。

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

来源:http://blog.csdn.net/qq1131410679/article/details/65934698

标签:java,对象,克隆
0
投稿

猜你喜欢

  • 详解Android Flutter中SliverAppBar的使用教程

    2023-06-23 12:11:27
  • Android编程实现WebView自适应全屏方法小结

    2022-09-20 09:33:09
  • Java里的static import使用小结

    2023-08-18 18:36:36
  • C# 常用日期时间函数(老用不熟)

    2021-08-21 10:12:18
  • DevExpress设置饼状图的Lable位置实例

    2022-02-02 15:53:37
  • Android实现WebView删除缓存的方法

    2023-02-19 08:38:22
  • SpringBoot+Prometheus+Grafana实现应用监控和报警的详细步骤

    2023-10-02 06:40:26
  • Android编程四大组件之BroadcastReceiver(广播接收者)用法实例

    2023-07-23 16:45:39
  • 详解C#中Helper类的使用

    2021-10-05 07:37:28
  • C#中使用快速排序按文件创建时间将文件排序的源码

    2023-06-04 08:19:19
  • Java File类 mkdir 不能创建多层目录的解决

    2022-12-01 09:20:18
  • 详解java中的6种单例写法及优缺点

    2021-06-01 17:26:01
  • 小程序与后端Java接 口交互实现HelloWorld入门

    2023-11-04 18:55:31
  • C#多线程ThreadPool线程池详解

    2021-06-06 20:37:17
  • 深入了解Spring中的@Autowired和@Resource注解

    2021-09-19 06:57:20
  • 详解Android的.aar文件生成方法以及使用技巧

    2023-08-06 06:43:20
  • 简单了解Java多态向上转型相关原理

    2023-10-11 16:11:01
  • Java实现红黑树(平衡二叉树)的详细过程

    2021-08-08 15:03:12
  • Spring整合WebSocket应用示例(上)

    2023-05-05 10:09:21
  • 使用@PathVariable接收两个参数

    2022-12-08 14:21:04
  • asp之家 软件编程 m.aspxhome.com