1背景分析
在 Java 开发中,对象拷贝或者说对象克隆是常有的事,对象克隆最终都离不开直接赋值、浅拷贝、深拷贝 这三种方式,我们常用的对象的转化方式,使用的是spring的
BeanUtils.copyProperties(Object source, Object target)
但是他不能拷贝复杂的对象,例如-对象中存在例外对象的引用。当我们自己需要拷贝复杂的对象的时候,就需要自己写深拷贝去赋值。
2.基础知识
2.1值类型
Java的基本数据类型:byte,short,int,long ,float,double,char,boolean…
2.2引用类型
自定义的类和Java中的包装类
String,Integer等
3.直接赋值
new 一个对象,直接把值赋值给另一个对象,他们同时指向内存中的一个地址。也就是共用一个引用,改变一个的值,另一个的值也会改变。
看这个例子,是一个很明显的直接赋值的引用,有如下情况
person对象:Person{name=‘我不是张三了’, age=20, email=‘123456@’, desc=‘我是张三’}
person1对象:Person{name=‘我不是张三了’, age=20, email=‘123456@’, desc=‘我是张三’}
4.浅拷贝
定义:如果原型对象的成员变量是值类型,将复制一份给克隆对象,也就是说在堆中拥有独立的空间;如果原型对象的成员变量是引用类型,则将引用对象的地址复制一份给克隆对象,也就是说原型对象和克隆对象的成员变量指向相同的内存地址。
换句话说,在浅克隆中,当对象被复制时只复制它本身和其中包含的值类型的成员变量,而引用类型的成员对象并没有复制
解释一波:语文不好的可能理解这句话有点费劲,大概的意思就是,基本数据类型在深拷贝的过程中,将会复制一份,在堆空间中将会有独立的空间,如果是引用的类型,意思就是2个对象同时指向一个引用,不会重新在堆中创建一个对象。
但是下面的这个例子,跟我们预期的结果不一样。
有2个答案
A 选项
person对象:Person{name=‘张三’, age=20, email=‘123456@’, desc=‘我是张三’}
person1对象:Person{name=‘我是张三的克隆对象’, age=22, email=‘123456@’, desc=‘我是张三’}
B选项
person对象:Person{name=‘我是张三的克隆对象’, age=20, email=‘123456@’, desc=‘我是张三’}
person1对象:Person{name=‘我是张三的克隆对象’, age=22, email=‘123456@’, desc=‘我是张三’}
确定的答案是A,好像跟上面将的概念不一样,浅拷贝的类型引用的地址,他们的值应该是一样的,但是现在确出现的不一样的情况。?????
分析一波:
String,Integer 都知道是包装类,且他们都是不可变的。当我们要修改他的值的时候,需要在内存中重新生成一个新的值,然后将原来的引用指向新的引用,原来的值没有改变。
5.深拷贝
定义:深拷贝是一种完全拷贝,无论是值类型还是引用类型都会完完全全的拷贝一份,在内存中生成一个新的对象,简单点说就是拷贝对象和被拷贝对象没有任何关系,互不影响
5.1 两中实现方式
5.1.1 全部的类都实现Cloneable接口
5.1.2实现Serializable接口
核心代码