相关介绍
快速理解
简而言之,言而简之,就是 “复制粘贴” 。
浅拷贝/深拷贝
浅拷贝和深拷贝是相对的,如果一个对象内部只有基本数据类型,那用clone()方法获取到的就是这个对象的深拷贝,而如果其内部还有引用数据类型,那用clone()方法就是一次浅拷贝的操作(如下图)。
注意两点:
· 原型对象和副本对象是不同的对象(hashcode不同、内存地址也不同)
· 浅拷贝的引用类型指向同一个对象。
代码实现
代码目录
浅拷贝
修改v2中date的值会改变v1中date的值,v1和v2指向同一个date。
代码如下:
Video类
import java.util.Date;
/**步骤:
*1、实现一个接口 Cloneable
* 2、重写一个方法 clone()
*/
public class Video implements Cloneable{
private String name;
private Date createtime;
@Override
protected Object clone() throws CloneNotSupportedException{
return super.clone();
}
//实现一个无参构造
public Video(){
}
//实现一个有参构造
public Video(String name,Date createtime){
this.name=name;
this.createtime=createtime;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getCreatetime() {
return createtime;
}
public void setCreatetime(Date createtime) {
this.createtime = createtime;
}
@Override
public String toString() {
return "Video{" +
"name='" + name + '\'' +
", createtime=" + createtime +
'}';
}
}
Bilibili类
package Prototype.lightClone
import java.util.Date;
/**
* 客户端:克隆
*/
public class Bilibili {
public static void main(String[] args) throws CloneNotSupportedException {
//原型对象v1
Date date=new Date();
Video v1=new Video("向狂神说java学习",date);
//v2由v1复制而来,强制转换成Video类型
//克隆出来的对象是和原来一模一样的,相当于Video v2=new Video("向狂神说java学习",date);
Video v2=(Video) v1.clone();
//v1和v2的原始值
System.out.println("v1=>"+v1+"\thashCode:"+v1.hashCode());
System.out.println("v2=>"+v2+"\thashCode:"+v2.hashCode());
System.out.println("========修改引用数据类型,原对象和副本都会变化=========");
date.setTime(22222222); //修改date后,v1、v2中的date都会变
System.out.println("v1=>"+v1);
System.out.println("v2=>"+v2);
System.out.println("=========修改基本数据类型,只有被修改的对象会变化==========");
//修改v2后,再次输出v2这个对象
v2.setName("Clone狂神说java"); //但是修改v2的name,不会影响v1
System.out.println("v1=>"+v1);
System.out.println("v2=>"+v2);
}
}
运行结果:
深拷贝
修改v2中date的值不会改变v1中date的值。
深克隆的实现方法可以使用序列化和反序列化,这里使用更简单的——修改clone()方法。
代码如下:
BiliBili类(同浅拷贝的Bilibili类)
//copy from lightClone
Video类(在上面Video类的基础上修改clone()方法)
import java.util.Date;
/**步骤:
*1、实现一个接口 Cloneable
* 2、重写一个方法 clone()
*/
public class Video implements Cloneable{
···
@Override
protected Object clone() throws CloneNotSupportedException{
Object obj=super.clone();
//实现深克隆
Video v=(Video) obj;
//将这个对象的属性也克隆
v.createtime=(Date) this.createtime.clone();
//v和obj都是引用,都指向堆中的同一个对象,因此可直接返回obj而不返回v
return obj;
}
···
}
运行结果:
系列文章目录
一、单例模式
二、工厂模式
三、建造者模式
四、原型模式
五、适配器模式
六、代理模式
七、装饰器模式
八、迭代器模式
九、模板方法模式
十、策略模式
十一、责任链模式
十二、观察者模式
总结、12种常用设计模式