Java基础-复制-深拷贝

时间:2024-03-15 20:30:03

如何绝对的拷贝这个对象,使这个对象完全独立于原对象?
这时候可以使用深拷贝.
在实际使用时,我们肯定是希望新拷贝出来的对象不受原对象的影响,否则咱们做出拷贝的意义何在?(我就碰到过因为对象被同事插进来的代码导致对象发生了变更,代码出现BUG的问题,后面是使用的深拷贝才消除同事的代码对该对象的影响)
深拷贝概念:
在对引用数据类型进行拷贝的时候,创建了一个新的对象,并且复制其内的成员变量.
在这里插入图片描述
在具体实现深拷贝上,这里提供两个方式,重写clone()方法和序列法

重写clone()方法

如果要使用这种方法,那么就要将类中所有自定义引用变量的类也实现Cloneable接口实现clone()方法

//Father clone()方法
@Override
protected Father clone() throws CloneNotSupportedException {
    return (Father) super.clone();
}
//Son clone()方法
@Override
protected Son clone() throws CloneNotSupportedException {
    Son son= (Son) super.clone();//待返回克隆的对象
    son.name=new String(name);
    son.father=father.clone();
    return son;
}

结果如下:

Son{age=13, name='son1', father=Father{name='bigFather'}}
Son{age=13, name='son1', father=Father{name='bigFather'}}
s1==s2:false
s1.name==s2.name:false

s1.Father==s2.Father:false
s1.name==s2.name:false
Son{age=12, name='son222', father=Father{name='smallFather'}}
Son{age=13, name='son1', father=Father{name='bigFather'}}

序列化

如果引用数量太多,或者层数太多了使用深拷贝会让人绝望!
那么我们可以使用序列化的方式来实现深拷贝
在这里插入图片描述
序列化后,将二进制字节流内容写到一个媒介(文本或字符数组),然后通过这个媒介读取数据,原对象写入这个媒介后拷贝给clone对象,原对象的修改不会影响clone对象,因为clone对象是从这个媒介读取的.
熟悉对象缓存的知道Java对象存在Redis中,在Redis中读取出来生成Java对象,这就需要用到序列化和反序列化.
一般是将Java对象存储为字节流或者Json串然后反序列化成Java对象.
因为序列化会储存对象的属性但是无法存储对象在内存中地址相关信息,所以在反序列化成Java对象的时候会重新创建所有的引用对象.
具体实现上:
自定义类需要实现Serializable接口,在需要深拷贝的类(Son)中定义一个函数返回该类对象.

protected Son deepClone() throws IOException, ClassNotFoundException {
      Son son=null;
      //在内存中创建一个字节数组缓冲区,所有发送到输出流的数据保存在该字节数组中
      //默认创建一个大小为32的缓冲区
      ByteArrayOutputStream byOut=new ByteArrayOutputStream();
      //对象的序列化输出
      ObjectOutputStream outputStream=new ObjectOutputStream(byOut);//通过字节数组的方式进行传输
      outputStream.writeObject(this);  //将当前student对象写入字节数组中

      //在内存中创建一个字节数组缓冲区,从输入流读取的数据保存在该字节数组缓冲区
      ByteArrayInputStream byIn=new ByteArrayInputStream(byOut.toByteArray()); //接收字节数组作为参数进行创建
      ObjectInputStream inputStream=new ObjectInputStream(byIn);
      son=(Son) inputStream.readObject(); //从字节数组中读取
      return  son;
}

结果

Son{age=13, name='son1', father=Father{name='bigFather'}}
Son{age=13, name='son1', father=Father{name='bigFather'}}
s1==s2:false
s1.name==s2.name:false

s1.Father==s2.Father:false
s1.name==s2.name:false
Son{age=12, name='son222', father=Father{name='smallFather'}}
Son{age=13, name='son1', father=Father{name='bigFather'}}