Java拷贝可分为三种:浅拷贝(Shallow Copy)、深拷贝(Deep Copy)、延迟拷贝(Lazy Copy)。除了java中的基本数据类型(int,long,short等。),还有引用数据类型,如string和对象实例。对于基本数据类型,实际上是复制其值,而对于引用数据类型,复制是其引用,没有创建新的对象,即没有分配新的内存空间。这种拷贝叫浅拷贝。深拷贝是指在引用类型进行拷贝时,创建新的对象,即将新的内存空间分配给拷贝对象。我们来看看浅拷贝和深拷贝的区别。众所周知,list本质上是一个数组,而数组是以地址的形式存储的。如上图所示list 给list一个浅拷贝 B,由于是浅拷贝,A的内容直接复制给B。java中相同内容的数组指向相同的地址,即在浅拷贝后,a和B指向相同的地址。结果是,在改变B的同时,也会改变A,因为改变B是改变B指向地址的内容,因为A也指向同一地址,所以A和B一起改变。几种浅拷贝1、复制遍历循环1 List<Person> destList = new ArrayList<Person>(srcList.size()); 2 for(Person p : srcList){ 3 destList.add(p); 4 } 2、Listt实现类的结构方法<Person> destList = new ArrayList<Person>(srcList); 3、使用list.addAll()List方法<Person> destList = new ArrayList<Person>(); destList.addAll(srcList); 4、使用System.arraycopy()方法1 Person[] srcPersons=srcList.toArray(new Person[0]); 2 Person[] destPersons=new Person[srcPersons.length]; 3 System.arraycopy(srcPersons, 0, destPersons, 0, srcPersons.length); 5、使用StreamcopyListt<Person> destList = srcList.stream().collect(Collectors.toList());测试及结果 1 printList(destList); ////打印A之前没有改变B 2 srcList.get(0).setAge(100);//改变B 3 printList(destList); ////打印改变B后的A 4 ///打印结果 5 123-->20 6 ABC-->21 7 abc-->22 8 123-->100 9 ABC-->21 10 abc-->22 如图所示,List深度复制,在将A复制到B的同时,为B创建新的地址,然后将地址A的内容传递到地址B。Lista与ListB内容一致,但由于指向的地址不同,相互变化不受影响。1.使用序列化方法 1 /** 2 * 深度复制集合 3 * 注意需要年泛型的序列化(实现serializable) 4 * 5 * @param src 6 * @param <T> 7 * @return 8 * @throws IOException 9 * @throws clasnotfoundexception */11 public static <T> List<T> deepCopy(List<T> src) {12 try (ByteArrayOutputStream byteOut = new ByteArrayOutputStream();13 ObjectOutputStream outputStream = new ObjectOutputStream(byteOut);14 ) {15 outputStream.writeObject(src);16 try (ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());17 ObjectInputStream inputStream = new ObjectInputStream(byteIn);18 ) {19 return (List<T>) inputStream.readObject();20 }21 } catch (Exception e) {22 ThrowableUtils.getString(e);23 }24 return Collections.emptyList();25 }2.clone方法 1 public class A implements Cloneable { 2 public String name[]; 3 public A(){ name=new String[2]; } 4 public Object clone() { 5 A o = null; 6 try { 7 o = (A) super.clone(); 8 } catch (CloneNotSupportedException e) { 9 e.printStackTrace(); 10 } return o; 11 } 12 } 13 14 for(int i=0;i<n;i+=){ 15 copy.add((A)src.get(i).clone()); 16 }Java对象的处理不同于基本数据类型。在Java中,以对象为入口参数的传输缺少为“引用传输”,即只传递一个“引用”,与C语言中的指针引用相同。在Java中,以对象为入口参数的传输缺少为“引用传输”,即只传输一个“引用”,这个“引用”的概念与C语言中的指针引用相同。当函数体内输入变量发生变化时,本质上是对对象的直接操作。 除函数传值时为“引用传递”外,在任何使用中”=“向对象变量赋值时,都是“引用传递”。测试及结果 1 printList(destList); ////打印A之前没有改变B 2 srcList.get(0).setAge(100);//改变B 3 printList(destList); ////打印改变B后的A 4 5 123-->20 6 ABC-->21 7 abc-->22 8 123-->20 9 ABC-->21 10 abc-->22 在浅复制的情况下,在源数据被修改和破坏后,指向数据目标集合的相应元素也发生了相同的变化。因此,在需求要求必须深度复制的情况下,如果使用上述方法,请确保List中的T对象不易被外部修改和损坏。因此,在需求要求必须深度复制的情况下,如果使用上述方法,请确保List中的T对象不易被外部修改和损坏。参考: