前言:学习总结浅拷贝与深拷贝
概念 拷贝 java中的对象拷贝(Object Copy)指的是将一个对象的所有属性(成员变量)拷贝到另一个有着相同类类型的对象中去
浅拷贝与深拷贝。 在Java语言里,当我们需要拷贝一个对象时,有两种类型的拷贝:浅拷贝(Shallow Copy)与深拷贝(Deep Copy)。
基本数据类型,直接进行值传递,浅拷贝与深拷贝一样
String略特殊,因为字符串实际是不可修改的,存放在常量池中,但代码层的表现与对象是一样的
浅拷贝只是拷贝了源对象的地址,所以源对象的值发生变化时,拷贝对象的值也会发生变化。(同一个引用,同一个对象)
深拷贝则是拷贝了源对象的所有值,所以即使源对象的值发生变化时,拷贝对象的值也不会改变。(不同的引用,不同的对象(同一个类))
实现方式
构造函数
实现Cloneable接口并重写Object的clone()方法或者
对象序列化实现深拷贝
Bean类 Address类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 public class Address { private String province; private String city; public Address () { } public Address (String province, String city) { this .province = province; this .city = city; } public String getCity () { return city; } public void setCity (String city) { this .city = city; } public String getProvince () { return province; } public void setProvince (String province) { this .province = province; } }
User类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 public class User { private String username; private Address address; public User () { } public User (String username,Address address) { this .username = username; this .address = address; } public String getUsername () { return username; } public void setUsername (String username) { this .username = username; } public Address getAddress () { return address; } public void setAddress (Address address) { this .address = address; } }
通过构造方法拷贝 代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class Solution { public static void main (String[] args) { User user = new User("张三" ,new Address("广东" ,"深圳" )); User copyUser1 = new User(user.getUsername(),user.getAddress()); User copyUser2 = new User(user.getUsername(),new Address(user.getAddress().getProvince(),user.getAddress().getCity())); System.out.println(user.getAddress() == copyUser1.getAddress()); System.out.println(user.getAddress() == copyUser2.getAddress()); } }
结果
通过clone()浅拷贝 User类实现Cloneable类并重写clone方法
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public class User implements Cloneable { private String username; private Address address; @Override public Object clone () { Object obj = null ; try { obj = super .clone(); } catch (Exception e) { e.printStackTrace(); } return obj; } }
1 2 3 4 5 6 7 8 9 10 11 class Solution { public static void main (String[] args) { User user = new User("张三" ,new Address("广东" ,"深圳" )); User copyUser = (User)user.clone(); System.out.println(user.getAddress() == copyUser.getAddress()); } }
结果
true
通过clone()深拷贝 与通过重写clone方法实现浅拷贝的基本思路一样,只需要为对象图的每一层的每一个对象都实现Cloneable接口并重写clone方法,最后在最顶层的类的重写的clone方法中调用所有的clone方法即可实现深拷贝。
简单的说就是:每一层的每个对象都进行浅拷贝=深拷贝。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 public class User implements Cloneable { private String username; private Address address; @Override public Object clone () { Object obj = null ; try { obj = super .clone(); User user = (User)obj; user.setAddress((Address)user.getAddress().clone()); } catch (Exception e) { e.printStackTrace(); } return obj; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public class Address implements Cloneable { private String province; private String city; @Override public Object clone () { Object obj = null ; try { obj = super .clone(); } catch (Exception e) { e.printStackTrace(); } return obj; } }
结果
false
序列化实现深拷贝 代码
实现Serializable接口
1 2 3 4 5 6 7 public class Address implements Serializable { } public class User implements Serializable { }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 class Solution { public static void main (String[] args) { User user = new User("张三" , new Address("广东" , "深圳" )); User copyUser = null ; try { ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos); oos.writeObject(user); oos.flush(); ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray())); copyUser = (User) ois.readObject(); } catch (Exception e) { e.printStackTrace(); } System.out.println(user.getAddress() == copyUser.getAddress()); } }
工具类依赖
1 2 3 4 5 <dependency > <groupId > org.apache.commons</groupId > <artifactId > commons-lang3</artifactId > <version > 3.9</version > </dependency >
1 2 3 4 5 6 7 8 9 10 11 12 class Solution { public static void main (String[] args) { User user = new User("张三" , new Address("广东" , "深圳" )); User copyUser = SerializationUtils.clone(user); System.out.println(user.getAddress() == copyUser.getAddress()); } }
结果
false
总结