java的浅拷贝与深拷贝(java clone)

刚才在总结原型设计模式的时候,觉得有必要把java的clone拿出来分析一下

想一想,为什么需要克隆?

为什么不重新new一个?道理很简单,目的是想要两个相同的对象,重新new一个还得自己重新赋值,太麻烦

如何克隆一个对象,初学者可能会这样写

这确实是做了克隆,但是是做了克隆引用,我们可以修改下student的值,看看cope拿到的值是什么

这个克隆的图示分析:我们希望的克隆是这样的

然而这个克隆的引用是这样的:

这样的话,改对象的值,这两个引用对象都会变,不是我们想要的结果

那我们来看下,java是怎样实现对象的克隆的

Object类中的clone

  1. 克隆对象和原对象不是同一个对象,占用不同的内存地址
  2. 克隆对象和原对象应该具有相同的类型,但它不是强制性的
  3. 克隆对象和原对象使用equals()方法比较应该是相等的,但它不是强制性的
  4. 因为每个类的基类都是Object,所以都有clone方法,但是它是protected,所以不能在类外访问 克隆一个对象,需要对clone重写

如何实现克隆(实现Cloneable接口,覆写clone方法)

  • 浅克隆:原对象和克隆对象不同,但对象内的成员引用相同
  • 深克隆:原对象和克隆对象不同,且对象内的成员引用不同 

不逼逼,直接上代码:

可以看出来,这样克隆出来的对象地址是不一样的,其中一个对象里面的基本数据类型(还有String类型)的改变不影响另外一个对象的值,如果是包装类型的数据就不行了,乐意看下:

这是实现克隆接口,覆写clone的的代码:

这样的clone就是浅copy,把对象赋值一份,但是对象里面的对象却是复制的应用,想要都复制,就需要用深copy

深克隆

有两种实现方法

  1. 多层实现Cloneable类
  2. 利用序列化和反序列化

多层实现的Cloneable(就是把Bag这个类也实现Cloneable接口,覆写clone方法,然后在Student的clone方法里面执行Bag的clone方法)

 
 

总结:这样虽然也能解决,但是需要Bag类也实现接口,覆写方法,如果Bag类里面也有方法,还要覆写这一套,很麻烦,如果类的解构简单可以使用这种方法,复杂的话,可以使用序列化和反序列化实现深克隆

(需要Student和Bag实现序列化接口,student覆写clone方法)代码如下:

这种方法就是利用序列化对象后将其copy到流里面,而原对象仍在jvm中,然后从流中将其反序列化成另外一个对象到jvm中,从而实现深克隆

发布了62 篇原创文章 · 获赞 68 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/oldshaui/article/details/101282215