一 demo演示
1 Professor类
1 class Professor implements Serializable, Cloneable { 2 private static final long serialVersionUID = 1286716519490813020L; 3 public String name; 4 public int age; 5 6 // 构造函数是为了CloneUtils json序列化使用 7 public Professor() { 8 } 9 10 public Professor(String name, int age) { 11 this.name = name; 12 this.age = age; 13 } 14 15 public Object clone() throws CloneNotSupportedException { 16 return super.clone(); 17 } 18 }
2. Student类
1 class Student implements Serializable, Cloneable { 2 private static final long serialVersionUID = -547004870369127943L; 3 public String name; 4 public int age; 5 public Professor p; 6 7 // 构造函数是为了CloneUtils工具类clazz.instance()方法调用 & json序列化使用 8 public Student() { 9 } 10 11 public Student(String name, int age, Professor p) { 12 this.name = name; 13 this.age = age; 14 this.p = p; 15 } 16 17 public Object shallowClone() throws CloneNotSupportedException { 18 Student s = (Student) super.clone(); 19 //s.p = (Professor) p.clone(); //这句加上就是深拷贝了 20 return s; 21 } 22 }
3 CloneUtils类
1 @SuppressWarnings("unchecked") 2 public class CloneUtils { 3 4 /** 5 * 浅拷贝 6 */ 7 public static <T> T shallowClone(T t) { 8 try { 9 if (t == null) { 10 return null; 11 } 12 13 Class<? extends T> clazz = (Class<? extends T>) t.getClass(); 14 T instance = clazz.newInstance(); 15 16 Field[] fields = clazz.getDeclaredFields(); 17 if (fields != null) { 18 for (Field field : fields) { 19 int modifiers = field.getModifiers(); 20 if (Modifier.isFinal(modifiers) || Modifier.isStatic(modifiers)) { //final的无法拷贝, static的无需拷贝 21 continue; 22 } 23 field.setAccessible(true); 24 field.set(instance, field.get(t)); 25 } 26 } 27 return instance; 28 } catch (Exception e) { 29 System.out.printf("error" + e); 30 // ignore 31 } 32 return null; 33 } 34 35 /** 36 * 深拷贝 37 */ 38 public static <T> T deepClone(T t, Class<T> clazz) throws IOException { 39 try { 40 if (t == null || clazz == null) { 41 return null; 42 } 43 return JsonUtils.toBean(JsonUtils.toJson(t), clazz); 44 } catch (Exception e) { 45 System.out.printf("error" + e); 46 // ignore 47 } 48 return null; 49 } 50 }
4 Main
1 class Main { 2 public static void main(String[] args) throws IOException, ClassNotFoundException, CloneNotSupportedException { 3 Professor p = new Professor("教授1", 50); 4 Student s1 = new Student("学生1", 18, p); 5 // Student s2 = (Student) s1.shallowClone(); 6 // Student s2 = CloneUtils.shallowClone(s1); 7 Student s2 = CloneUtils.deepClone(s1, Student.class); 8 s2.p.name = "教授2"; 9 s2.p.age = 30; 10 s2.name = "学生2"; 11 s2.age = 25; 12 System.out.println(s1.name + " " + s1.age + " " + s1.p.name + " " + s1.p.age); 13 } 14 }
第5行输出结果: 学生1 18 教授2 30
第6行输出结果: 学生1 18 教授2 30
第7行输出结果: 学生1 18 教授1 50
二 分析
上面的shallow clone只是实体的所有数据&引用进行了简单拷贝,这样会出现修改拷贝类s2中的引用指针p时,会影响原始的实体s1.p,造成不可预知的错误
可以看到把Student类中的引用p也进行clone就是深拷贝了(Student#line19注释打开)
或者直接用序列化的方式进行深拷贝,深拷贝的原始实体和拷贝实体毫无关系,不会互相影响