最近,在项目中遇到了一个奇怪的问题,当不断复制当前对象并修改加入list,发现前面的对象值都被最后一个对象的值覆盖了。最后发现是java的拷贝的问题。
java中的拷贝
1.引用拷贝
//引用拷贝
private static void copyReferenceObject(){
Person p = new Person(18, "mj");
Person p1 = p;
System.out.println(p);
System.out.println(p1);
}
这里打印的结果:
Person@3654919e
Person@3654919e
输出结果:二者的引用是同一个对象,指向同一个地址,并没有创建出一个新的对象,所以修改一个对象值,会改变另一个。
2.对象拷贝
对象拷贝可以分为浅拷贝、深拷贝
(1)浅拷贝(clone):如果对象中的所有数据域都是数值或者基本类型,使用clone()即可满足需求。
- 首先,被复制的类需要实现Clonenable接口(不实现的话在调用clone方法会抛出CloneNotSupportedException异常)
- 其次,覆盖clone()方法,访问修饰符设为public
- 最后,直接调用该方法即可
Person p = new Person();
Person p1 = p.clone();
这样p和p1分别指向不同的对象。
(2)深拷贝:如果在对象中包含子对象的引用,拷贝的结果是使得两个域引用同一个对象,默认的拷贝是浅拷贝,没有拷贝包含在对象中的内部对象。
- 子对象也必须实现如该对象一样实现Clonenable接口以及clone方法
- 如果对象中包括对个子对象,每个子对象都实现克隆比较复杂,可以直接使用Serializable接口,每个类都要实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆