一:需求背景
有时候在写工程的时候,已经有一个对象了,但是需要重新生成一个对象,并且想把之前对象的部分字段信息或者全部信息copy过来,这个时候可以使用new 对象,然后一行行copy的方式。这样子会很麻烦如果这个类有100个字段,那得要写101代码才行。此时可以选择使用clone的方法 clone方法是在Object对象中的,也就是所有类默认都继承了此方法,但是如果想要使用clone功能必须还要implements Clonnable接口,表示此类可以clone,同时默认的clone是“浅clone”,他只会把对象的一些基本数据类型clone,而一些对象属性无法做深度clone,回和上一个对象共用,这样就会导致修改时相互影响,如果想要实现“深度clone”,需要自己@override clone方法,先clone,然后在创建那些属性对应的对象,在把原来的值copy过来。
二:代码实现
-
1、实体类Student.java
package com.surfilter; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * 实体类实现Cloneable接口,此接口没有任何抽象方法,只是一个标记而已 * 真正的clone方法是在Object类中, 但是clone方法是protected的,所以不能再外面使用 * 只能在本类中创建一个方法来间接调用clone方法 * 默认是“浅clone”,如果需要实现“深度clone”,则需要先supper.clone(),然后在创建属性对象。 * * [@Author](https://my.oschina.net/arthor) liufu * [@Company](https://my.oschina.net/u/3478402) 任子行网络技术股份有限公司 * @CreateTime 2018/1/7 14:01 */ public class Student implements Cloneable { private String userName; private String age; private List<String> project; public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getAge() { return age; } public void setAge(String age) { this.age = age; } public List<String> getProject() { return project; } public void setProject(List<String> project) { this.project = project; } /** * 创建一个方法间接调用clone,因为clone是protected的,外面无法调用 * * [@return](https://my.oschina.net/u/556800) */ public Student newInstance() { try { //这样是浅copy,如果想要深度copy则需要重写clone方法 return (Student) this.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return null; } /** * 深度clone实现 * * @return * @throws CloneNotSupportedException */ @Override protected Object clone() throws CloneNotSupportedException { //这里只是copy了userName和age, // 那个project还是指向了之前的地址,和之前的student使用同一个对象,这样修改的话会相互影响 Student clone = (Student) super.clone(); List<String> p1 = clone.getProject(); if (p1 != null) { ArrayList<String> p2 = new ArrayList<>(p1.size()); Collections.copy(p1, p2); clone.setProject(p2); } return clone; } }
-
2、主类CloneTest.java
package com.surfilter; import java.util.ArrayList; /** * @Author liufu * @Company 任子行网络技术股份有限公司 * @CreateTime 2018/1/7 14:00 */ public class CloneTest { public static void main(String[] args) { Student s1 = new Student(); ArrayList<String> p1 = new ArrayList<>(); s1.setUserName("zhangsan"); s1.setAge("23"); s1.setProject(p1); Student s2 = s1.newInstance(); s2.setUserName("lisi"); s2.setAge("53"); System.out.println(s1.getUserName() + ":" + s1.getAge()); System.out.println(s2.getUserName() + ":" + s2.getAge()); //浅clone,对象属性测试(没有重写clone方法) System.out.println(s1.getProject() == s2.getProject()); //输出true //深度clone,对象属性测试(重写clone方法) System.out.println(s1.getProject() != s2.getProject()); //输出true } }
-
3、数组,集合copy
String[] src = new String[1024]; src[0] = "0"; src[1] = "1"; src[2] = "2"; src[3] = "3"; src[7] = "4"; src[8] = "5"; String[] dest = new String[1024]; System.arraycopy(src, 0, dest, 0, src.length); ArrayList<String> srcList = new ArrayList<>(1024); srcList.add(""); srcList.add(""); srcList.add(""); srcList.add(""); srcList.add(""); ArrayList<String> destList = new ArrayList<>(srcList.size()); Collections.copy(destList, srcList);