【java】深拷贝实现的两种方式

 2022-09-16
原文地址:https://callmejacky.blog.csdn.net/article/details/98630429

最近在做项目时,遇到一个java深拷贝的问题,常见有两种方式:

  1. 实现Cloneable接口,并且重写Object类中的clone()方法
  2. 实现Serializable接口序列化

详情请移步:Java对象-深拷贝(实现Serializable, Cloneable两种方式)

1. 实现Cloneable接口

    public class Demo implements Cloneable {
    
        private String name;
    
        private String value;
    
        private DemoInternal demoInternal;
    
        /*省略getter和setter方法*/
    
        @Override
        public Demo clone() {
            Demo demo = null;
            try {
                demo = (Demo) super.clone(); //浅复制
            } catch (CloneNotSupportedException e) {
                e.printStackTrace();
            }
            demo.demoInternal = demoInternal.clone(); //深度复制
            return demo;
        }
    }
    public class DemoInternal implements Cloneable {
    
        private String internalName;
    
        private String internalValue;
    
        /*省略getter和setter方法*/
    
        @Override
        public DemoInternal clone() {
            DemoInternal demoInternal = null;
            try {
                demoInternal = (DemoInternal) super.clone();
            } catch (CloneNotSupportedException e) {
                e.printStackTrace();
            }
            return demoInternal;
        }
    }

2. 实现Serializable接口

    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.io.Serializable;
    
    /**
     * 通过字节流序列化实现深拷贝,需要深拷贝的对象必须实现Serializable接口
     * 
     * @author Administrator
     */
    public class CloneUtils {
    	@SuppressWarnings("unchecked")
    	public static <T extends Serializable> T clone(T obj) {
    		T cloneObj = null;
    		try {
    			// 写入字节流
    			ByteArrayOutputStream out = new ByteArrayOutputStream();
    			ObjectOutputStream obs = new ObjectOutputStream(out);
    			obs.writeObject(obj);
    			obs.close();
    
    			// 分配内存,写入原始对象,生成新对象
    			ByteArrayInputStream ios = new ByteArrayInputStream(out.toByteArray());
    			ObjectInputStream ois = new ObjectInputStream(ios);
    			// 返回生成的新对象
    			cloneObj = (T) ois.readObject();
    			ois.close();
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    		return cloneObj;
    	}
    }

3. 总结

上述的两种方式,都是通过一层又一层地深入,实现对象的深度复制。所以,如果您遇到类似于下面的问题时:

我已经实现了java.io.Serializable的接口了,为什么还提示我 NotSerializableException?

不要迷惑,一定是您忘记将某一个类实现Serializable接口,排错的方法是,使用try catch捕获异常,e.getMessage会打印出您忘记实现Serializable接口的类名,将该类实现Serializable接口即可。