欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-07-19 19:26:40
java 对象的克隆 一、对象的浅克隆 (1)需要克隆类需要重写object类的clone方法,并且实现cloneable接口(标识接口,无需实现任何方法) (2)...

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接口的。

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