文章目录
- 1、什么是浅拷贝?
- 2、什么是深拷贝?
- 2.1、常见的深拷贝方式
在Java语言中,当我们需要拷贝一个Java对象的时候,常见的会有两种方式的拷贝:浅拷贝与深拷贝。
- 浅拷贝:只是拷贝了源对象的地址,所以源对象的任何值发生改变时,拷贝对象的值也会随之而发生变化。
- 深拷贝:则是拷贝了源对象的所有值而不是地址,所以即使源对象的值发生任何变化时,拷贝对象的值也不会改变。
1、什么是浅拷贝?
浅拷贝代码演示(最常见的方式):
/*** 浅拷贝:拷贝的就是目标对象在堆内存中的地址* 注意:拷贝对象改变,源对象(目标对象)改变*/
public class SlowCopy {public static void main(String[] args) {User user = new User();user.setUserName("张三");user.setPassWord("123456");//浅拷贝User user1 = user ;System.out.println(user); //com.sqx.copy.bean.User@1b6d3586System.out.println(user1); //com.sqx.copy.bean.User@1b6d3586}
}
2、什么是深拷贝?
深拷贝的对象修改的时候,源对象是不受影响的!
2.1、常见的深拷贝方式
一般常用的深拷贝方式有如下5种
1、构造函数方式
/*** 构造器实现深拷贝 :我们拷贝对象和源对象是隔离的,互不干扰!*/
public class DeepCopy {public static void main(String[] args) {//深拷贝User user = new User("张三","123456");User user1 = new User("李四","654321");System.out.println(user); //com.sqx.copy.bean.User@1b6d3586System.out.println(user1); //com.sqx.copy.bean.User@4554617c}
}
2、重写Clone方法
1、实现Cloneable接口,Cloneable其实就是一个标记接口,只有实现这个接口后,然后在类中重写Object中的clone方法,然后通过类
调用clone方法才能克隆成功,如果不实现这个接口,则会抛出CloneNotSupportedException(克隆不被支持)异常。
public class Student implements Cloneable {private String userName ;private String passWord ; // 此处省略set\get方法 @Overridepublic Student clone() throws CloneNotSupportedException {return (Student) super.clone();}
}
2、代码演示深拷贝
/*** 重写clone方法实现深拷贝*/
public class DeepCopy01 {public static void main(String[] args) {Student student01 = new Student("张三","123456");Student student02 = null;try {student02 = student01.clone(); // 深拷贝对象} catch (CloneNotSupportedException e) {e.printStackTrace();}System.out.println(student01); //com.sqx.copy.bean.Student@1b6d3586System.out.println(student02); //com.sqx.copy.bean.Student@4554617cSystem.out.println(student01.equals(student02)); // true 标识内容相同,但是仅地址不同(记得重写equlas)}
}
我们发现拷贝的student02对象和源对象地址已经不同了,但是内容是一致的~
补充
我们的ArrayList 、LinkedList等都实现了Cloneable接口,支持深拷贝
public class ArrayList<E> extends AbstractList<E>implements List<E>, RandomAccess, Cloneable, java.io.Serializable {...
}
样例演示:
public class ArrayListCopyTest {public static void main(String[] args) {ArrayList<User> list = new ArrayList<>();User user = new User("张三", "123456");list.add(user) ;System.out.println("list: "+list); //源ArrayList对象ArrayList<User> clone = (ArrayList<User>) list.clone();System.out.println("clone: "+clone); //经过深拷贝得到的ArrayList对象System.out.println(list == clone); // false 经过深拷贝,创建的是新的对象System.out.println(list.get(0) == clone.get(0)); //true 说明拷贝对象和源对象的内容是一样的!}
}
总结:
- 浅拷贝只复制某个对象的引用,而不复制对象本身,新旧对象还是共享同一块内存
- 深拷贝会创造一个一摸一样的对象,新对象和原对象不共享内存,修改新对象不会改变原对对象
实现深拷贝的方式还有:Apache Commons Lang序列化、Gson序列化、jackson序列化等