天天看點

史上最清晰易懂的JAVA深克隆和淺克隆講解深入淺出了解面向對象的深克隆和淺克隆

深入淺出了解面向對象的深克隆和淺克隆

閱讀本文需要一定的面向對象基礎和JavaIO流的相應知識!

深克隆(要實作深克隆被克隆類以及被克隆類的引用必須實作Serializable接口)

(未實作接口會抛出NotSerializableException異常)

定義:被複制對象的所有變量都含有與原來的對象相同的值,除去那些引用其他對象的變量。那些引用其他對象的變量将指向被複制過的新對象,而不再是原有的那些被引用的對象。深克隆的是實作實際上是對對象的序列化和反序列化

淺克隆(要實作淺克隆被克隆的類必須實作Cloneable接口)

(未實作接口會跑出CloneNotSupportedException異常)

定義:被複制對象的所有變量都含有與原來的對象相同的值,而所有的對其他對象的引用仍然指向原來的對象。

詳細講解代及實作碼如下

實作類:

package com.xiaoqiang;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
/**
 * 本案例配合上文解說
 * 詳細講解java深克隆淺克隆的差別
 * @author xiaoqiang
 * @Time 2017年5月5日
 */
public class Student implements Cloneable,Serializable{
    private String name;
    private int age;
    private Date birthday;
    public Student(){
        super();
    }
    public Student(String name, int age, Date birthday) {
        super();
        this.name = name;
        this.age = age;
        this.birthday = birthday;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public Date getBirthday() {
        return birthday;
    }
    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
    @Override
    public String toString() {
        return "Student [name=" + name + ", age=" + age + ", birthday="
                + birthday + "]";
    }
    /**
     * 完成淺克隆類需實作Cloneable接口
     * @param student
     * @return Object
     */
    public Object shallowClone(Student student){
        try {
            return student.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 完成深克隆被克隆的類和類的引用類
     * 均實作Serializable接口
     * @param student
     * @return Object
     */
    public Object deepClone(Student student){
        /*
         *本次實作深克隆使用 ByteArrayOutputStream 
         * 和ByteArrayInputStream 
         *作為複制過程中字元數組存儲中介
         */
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos =null;
        ObjectInputStream ois = null;
        try {
            //将bos作為收集位元組數組中介
            oos= new ObjectOutputStream(bos);
            //将傳入參數student類寫入bos中
            oos.writeObject(student);
            //将讀取到資料傳入ObjectInputStream
            ois = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));
            return ois.readObject();
        } catch (IOException | ClassNotFoundException e) {
            //JDK 1.7後引入 可以同時用| 優化代碼可讀性
            e.printStackTrace();
            return null;
        } finally{
            try {
                bos.close();
                oos.close();
                ois.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    public static void main(String[] args) {
        Student student = new Student("小強",,new Date("1997","06","13"));
        System.out.println("原student類   "+student);
        //淺克隆對象shallowCloneStudent
        Student shallowCloneStudent = (Student) student.shallowClone(student);
        System.out.println("淺克隆出來的student   "+shallowCloneStudent);
        System.out.println("淺克隆和深克隆對象對比   "+shallowCloneStudent.equals(student));
        System.out.println("淺克隆Date和深克隆Date類引用是否相同   "+shallowCloneStudent.getBirthday().equals(student.getBirthday()));
        //深克隆對象deepCloneStudent
        Student deepCloneStudent = (Student) student.deepClone(student);
        System.out.println("深克隆出來的student   "+deepCloneStudent);
        System.out.println("深克隆和深克隆對象對比   "+deepCloneStudent.equals(student));
        System.out.println("深克隆Date和深克隆Date類引用是否相同   "+deepCloneStudent.getBirthday().equals(student.getBirthday()));

    }
}   
           

引用類

package com.xiaoqiang;

import java.io.Serializable;
/**
 * @author xiaoqiang
 * @Time 2017年5月5日
 */
public class Date implements Serializable{
    private String year;
    private String month;
    private String day;
    public Date(){}
    public Date(String year, String month, String date) {
        super();
        this.year = year;
        this.month = month;
        this.day = date;
    }
    public String getYear() {
        return year;
    }
    public void setYear(String year) {
        this.year = year;
    }
    public String getMonth() {
        return month;
    }
    public void setMonth(String month) {
        this.month = month;
    }
    public String getDate() {
        return day;
    }
    public void setDate(String date) {
        this.day = date;
    }
    @Override
    public String toString() {
        return year+"年"+month+"月"+day+"日";
    }
}