java对象深复制、浅复制(深拷贝、浅拷贝)的理解
先看一个例子
User user1 = new User(); user1.setId("111"); Map<String, User> map1 = new HashMap<>(); map1.put("a", user1); Map<String, User> map2 = new HashMap<>(); map2.putAll(map1); User user2 = map2.get("a"); user2.setId("222"); System.out.println("user1 id:"+user1.getId()); System.out.println("user2 id:"+user2.getId());
user1 id:222
user2 id:222
可以看到改了map2里的对象,map1里的也跟着改了。
所谓浅复制:则是只复制对象的引用,两个引用仍然指向同一个对象,在内存中占用同一块内存。被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。换言之,浅复制仅仅复制所拷贝的对象,而不复制它所引用的对象。
深复制:被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。换言之,深复制把要复制的对象所引用的对象都复制了一遍。
注意:直接map2=map1或者map2=map1.clone(),这些都是浅复制,另外map没有实现Cloneable接口,不过hashmap实现了。
关于java里克隆的理解:Java中的Cloneable接口理解
如何实现深拷贝?
利用java的序列化和反序列化,具体参阅java序列化反序列化深入探究(转)
1 User user1 = new User(); 2 user1.setId("111"); 3 HashMap<String, User> map1 = new HashMap<>(); 4 map1.put("a", user1); 5 6 HashMap<String, User> map2 = null; 7 ObjectOutputStream oos = null; 8 ObjectInputStream ois = null; 9 try { 10 oos = new ObjectOutputStream(new FileOutputStream("tempfile")); 11 oos.writeObject(map1); 12 13 ois = new ObjectInputStream(new FileInputStream("tempfile")); 14 map2 = (HashMap<String, User>) ois.readObject(); 15 } catch (IOException e) { 16 e.printStackTrace(); 17 } catch (ClassNotFoundException e) { 18 e.printStackTrace(); 19 } finally { 20 if (oos != null) { 21 try { 22 oos.close(); 23 } catch (IOException e) { 24 e.printStackTrace(); 25 } 26 } 27 if(ois != null){ 28 try { 29 ois.close(); 30 } catch (IOException e) { 31 e.printStackTrace(); 32 } 33 } 34 } 35 36 37 User user2 = map2.get("a"); 38 user2.setId("222"); 39 40 System.out.println("user1 id:"+user1.getId()); 41 System.out.println("user2 id:"+user2.getId());
user1 id:111
user2 id:222
更多知识可以参阅:Java中的不可变类理解