测试类:Human、Student、Teacher、Matser
/*
* @ProjectName: 编程学习
* @Copyright: 2018 HangZhou Yiyuery Dev., Ltd. All Right Reserved.
* @address: http://xiazhaoyang.tech
* @date: 2018/7/28 18:15
* @email: xiazhaoyang@live.com
* @description: 本内容仅限于编程技术学习使用,转发请注明出处.
*/
package com.capsule.jdk.clone;import lombok.Data;
import lombok.ToString;
import lombok.experimental.Accessors;/**
* <p>
*
* </p>
*
* @author xiazhaoyang
* @version V1.0
* @date 2018/7/28 18:15
* @modificationHistory=========================逻辑或功能性重大变更记录
* @modify By: {修改人} 2018/7/28
* @modify reason: {方法名}:{原因}
* ...
*/
@Data
@ToString
@Accessors(chain = true)
public class Human implements Cloneable{ /**姓名*/
private String name;
/**性别 男:true 女:false*/
private boolean sex; public Human() {
} public Human(String name, boolean sex) {
this.name = name;
this.sex = sex;
} /**
* 重载克隆方法
* @return
*/
@Override
public Object clone() {
Human s;
try {
s = (Human) super.clone();
} catch (CloneNotSupportedException e) {
throw new AssertionError(); // Can't happen
}
return s;
}
}
直接调用父类的clone方法会报CloneNotSupportedException异常
protected native Object clone() throws CloneNotSupportedException;
CloneNotSupportedException
这个异常。Cloneable
Cloneable
接口有关系浅复制
Teacher
:/*
* @ProjectName: 编程学习
* @Copyright: 2018 HangZhou Yiyuery Dev., Ltd. All Right Reserved.
* @address: http://xiazhaoyang.tech
* @date: 2018/7/28 15:57
* @email: xiazhaoyang@live.com
* @description: 本内容仅限于编程技术学习使用,转发请注明出处.
*/package com.capsule.jdk.clone;import lombok.Data;import lombok.ToString;import lombok.experimental.Accessors;/**
* <p>
* 老师对象
* </p>
*
* @author xiazhaoyang
* @version V1.0
* @date 2018/7/28 15:57
* @modificationHistory=========================逻辑或功能性重大变更记录
* @modify By: {修改人} 2018/7/28
* @modify reason: {方法名}:{原因}
* ...
*/@Data@ToString@Accessors(chain = true)public class Teacher implements Cloneable{ /**姓名*/
private String name; /**学科*/
private String subject;}
Matser
:/*
* @ProjectName: 编程学习
* @Copyright: 2018 HangZhou Yiyuery Dev., Ltd. All Right Reserved.
* @address: http://xiazhaoyang.tech
* @date: 2018/7/29 10:09
* @email: xiazhaoyang@live.com
* @description: 本内容仅限于编程技术学习使用,转发请注明出处.
*/package com.capsule.jdk.clone;import lombok.Data;import lombok.ToString;import lombok.experimental.Accessors;/**
* <p>
*
* </p>
*
* @author xiazhaoyang
* @version V1.0
* @date 2018/7/29 10:09
* @modificationHistory=========================逻辑或功能性重大变更记录
* @modify By: {修改人} 2018/7/29
* @modify reason: {方法名}:{原因}
* ...
*/@Data@ToString@Accessors(chain = true)public class Master implements Cloneable{ private String name; private StringBuffer sb = new StringBuffer(""); public Master() {
sb.append("first create.");
} public Master(String name) { this.name = name;
sb.append("first create.");
} public static void main(String[] args) throws CloneNotSupportedException {
Master m = new Master("zhaizhai");
Master m2 = (Master) m.clone();
System.out.println(m.toString());
System.out.println(m2.toString()); System.out.println("------------------------"); //变更属性
m.getSb().append("first append");
System.out.println(m.toString());
System.out.println(m2.toString()); //Master(name=zhaizhai, sb=first create.)
//Master(name=zhaizhai, sb=first create.)
//------------------------
//Master(name=zhaizhai, sb=first create.first append)
//Master(name=zhaizhai, sb=first create.first append) //不重写Object.clone()方法的话在目标类内部仍然可以调用目标类.clone(),
//但浅层拷贝导致m和m2共享同一个StringBuffer对象,这是很危险的 }
}
CloneTest
:/*
* @ProjectName: 编程学习
* @Copyright: 2018 HangZhou Yiyuery Dev., Ltd. All Right Reserved.
* @address: http://xiazhaoyang.tech
* @date: 2018/7/28 10:59
* @email: xiazhaoyang@live.com
* @description: 本内容仅限于编程技术学习使用,转发请注明出处.
*/package com.capsule.jdk.clone;import org.junit.Test;import org.springframework.util.Assert;/**
* <p>
* jdk clone 对象
* </p>
*
* @author xiazhaoyang
* @version V1.0
* @date 2018/7/28 10:59
* @modificationHistory=========================逻辑或功能性重大变更记录
* @modify By: {修改人} 2018/7/28
* @modify reason: {方法名}:{原因}
* ...
*/public class CloneTest { /**
* clone复制 [继承、对象嵌套]
*/
@Test
public void cloneStudent(){
Student s = new Student("zhangsan",Boolean.FALSE);
s.setTeacher(new Teacher().setName("zhailaoshi").setSubject("yuwen"));
Student s2 = (Student)s.clone();
s2.getTeacher().setName("zhaizhai");
Assert.isTrue(s.equals(s2)); //h.equals(h2) true
System.out.println(s.toString());
System.out.println(s2.toString()); //Student(super=Human(name=zhangsan, sex=false), teacher=Teacher(name=zhaizhai, subject=yuwen))
//Student(super=Human(name=zhangsan, sex=false), teacher=Teacher(name=zhaizhai, subject=yuwen))
} /**
* clone复制 [简单参数、clone实质是新建一个对象引用,但是属性和被克隆对象一致]
*/
@Test
public void cloneHuman(){
Human h = new Human().setName("zhangsan").setSex(Boolean.FALSE);
Human h2 = (Human)h.clone();
h2.setName("new zhangsan");
Assert.isTrue(!h.equals(h2)); // h.equals(h2) false
System.out.println(h.toString());
System.out.println(h2.toString()); //Human(name=zhangsan, sex=false)
//Human(name=new zhangsan, sex=false)
}
}
clone的重写
深度复制 调整Student、Teacher的clone达到深度clone的目标:
继承已重写clone的父类Human
Teacher
:/*
* @ProjectName: 编程学习
* @Copyright: 2018 HangZhou Yiyuery Dev., Ltd. All Right Reserved.
* @address: http://xiazhaoyang.tech
* @date: 2018/7/28 15:57
* @email: xiazhaoyang@live.com
* @description: 本内容仅限于编程技术学习使用,转发请注明出处.
*/package com.capsule.jdk.clone;import lombok.Data;import lombok.ToString;import lombok.experimental.Accessors;/**
* <p>
* 老师对象
* </p>
*
* @author xiazhaoyang
* @version V1.0
* @date 2018/7/28 15:57
* @modificationHistory=========================逻辑或功能性重大变更记录
* @modify By: {修改人} 2018/7/28
* @modify reason: {方法名}:{原因}
* ...
*/@Data@ToString@Accessors(chain = true)public class Teacher extends Human{ /**姓名*/
private String name; /**学科*/
private String subject; @Override
public Object clone(){ return super.clone();
}}
自己继承Cloneable接口实现clone方法:
Teacher
:/*
* @ProjectName: 编程学习
* @Copyright: 2018 HangZhou Yiyuery Dev., Ltd. All Right Reserved.
* @address: http://xiazhaoyang.tech
* @date: 2018/7/28 15:57
* @email: xiazhaoyang@live.com
* @description: 本内容仅限于编程技术学习使用,转发请注明出处.
*/package com.capsule.jdk.clone;import lombok.Data;import lombok.ToString;import lombok.experimental.Accessors;/**
* <p>
* 老师对象
* </p>
*
* @author xiazhaoyang
* @version V1.0
* @date 2018/7/28 15:57
* @modificationHistory=========================逻辑或功能性重大变更记录
* @modify By: {修改人} 2018/7/28
* @modify reason: {方法名}:{原因}
* ...
*/@Data@ToString@Accessors(chain = true)public class Teacher implements Cloneable{ /**姓名*/
private String name; /**学科*/
private String subject; @Override
public Object clone(){ try { return super.clone();
} catch (CloneNotSupportedException e) { throw new RuntimeException();
}
}}
重写Student的clone方法,对于内部的对象型引用,新建对象或使用clone方法的嵌套来实现深度clone的目的。
Student
:/*
* @ProjectName: 编程学习
* @Copyright: 2018 HangZhou Yiyuery Dev., Ltd. All Right Reserved.
* @address: http://xiazhaoyang.tech
* @date: 2018/7/28 11:00
* @email: xiazhaoyang@live.com
* @description: 本内容仅限于编程技术学习使用,转发请注明出处.
*/package com.capsule.jdk.clone;import lombok.Data;import lombok.ToString;import lombok.experimental.Accessors;/**
* <p>
*
* <li>拷贝对象返回的是一个新对象,而不是一个引用。<li/>
* <li>拷贝对象与用 new 操作符返回的新对象的区别就是这个拷贝已经包含了一些原来对象的信息,而不是对象的初始信息</li>
*
* </p>
*
* @author xiazhaoyang
* @version V1.0
* @date 2018/7/28 11:00
* @modificationHistory=========================逻辑或功能性重大变更记录
* @modify By: {修改人} 2018/7/28
* @modify reason: {方法名}:{原因}
* ...
*/@Data@ToString(callSuper = true)@Accessors(chain = true)public class Student extends Human{ /**班主任*/
private Teacher teacher; public Student(String name, boolean sex) { super(name,sex);
} public Student(String name, boolean sex,Teacher teacher) { super(name, sex); this.teacher = teacher;
} /**
* 重载克隆方法
* @return
*/
@Override
public Object clone() {
Student s = (Student) super.clone();
s.setTeacher((Teacher) teacher.clone()); //s.setTeacher(new Teacher(teacher.getName()))
return s;
}}
测试深复制后的效果
/**
* 修改Student的clone方法,并让Teacher继承Human以获得clone方法
*/@Testpublic void deepClone(){
Student s = new Student("zhangsan",Boolean.FALSE);
s.setTeacher(new Teacher().setName("zhailaoshi").setSubject("yuwen"));
Student s2 = (Student)s.clone();
s2.getTeacher().setName("zhaizhai");
Assert.isTrue(!s.equals(s2)); //h.equals(h2) false
System.out.println(s.toString());
System.out.println(s2.toString()); //Student(super=Human(name=zhangsan, sex=false), teacher=Teacher(name=zhailaoshi, subject=yuwen))
//Student(super=Human(name=zhangsan, sex=false), teacher=Teacher(name=zhaizhai, subject=yuwen))}