原型模式 —— Java的赋值、浅克隆和深度克隆的区别
赋值 直接 = ,克隆 clone
假如说你想复制一个简单变量。很简单:
int a= 5;
int b= a; b = 6; 这样 a == 5, b == 6
不仅仅是int类型,其它七种原始数据类型(boolean,char,byte,short,float,double.long)同样适用于该类情况。
但是如果你复制的是一个对象、list集合的情况下,情况就有些复杂了。

class Student {
private int number; public int getNumber() {
return number;
} public void setNumber(int number) {
this.number = number;
} }
public class Test { public static void main(String args[]) {
Student stu1 = new Student();
stu1.setNumber(12345);
Student stu2 = stu1; System.out.println("学生1:" + stu1.getNumber());
System.out.println("学生2:" + stu2.getNumber());
}
} 结果: 学生1:12345
学生2:12345

这就怪了,为什么改变学生2的学号,学生1的学号也发生了变化呢?
原因出在(stu2 = stu1) 这一句。该语句的作用是将stu1的引用赋值给stu2,
这样,stu1和stu2指向内存堆中同一个对象。如图:
要做到 赋值的两个对象之间的内存地址重新定义
实现对象克隆有两种方式:
1). 实现Cloneable接口并重写Object类中的clone()方法;

class Address implements Cloneable {
private String add; public String getAdd() {
return add;
} public void setAdd(String add) {
this.add = add;
} @Override
public Object clone() { // 下面 这个是重点
Address addr = null;
try{
addr = (Address)super.clone();
}catch(CloneNotSupportedException e) {
e.printStackTrace();
}
return addr;
}
}

2). 实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆。
如果引用类型里面还包含很多引用类型,或者内层引用类型的类里面又包含引用类型,使用clone方法就会很麻烦。这时我们可以用序列化的方式来实现对象的深克隆。

public class Outer implements Serializable{
private static final long serialVersionUID = 369285298572941L; //最好是显式声明ID
public Inner inner;
//Discription:[深度复制方法,需要对象及对象所有的对象属性都实现序列化]
public Outer myclone() {
Outer outer = null;
try { // 将该对象序列化成流,因为写在流里的是对象的一个拷贝,而原对象仍然存在于JVM里面。所以利用这个特性可以实现对象的深拷贝
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(this);
// 将流序列化成对象
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
outer = (Outer) ois.readObject();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return outer;
}
}

实现对象克隆有两种方式:
1). 实现Cloneable接口并重写Object类中的clone()方法;
2). 实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆。
注意:基于序列化和反序列化实现的克隆不仅仅是深度克隆,更重要的是通过泛型限定,可以检查出要克隆的对象是否支持序列化,这项检查是编译器完成的,不是在运行时抛出异常,这种是方案明显优于使用Object类的clone方法克隆对象。让问题在编译的时候暴露出来总是优于把问题留到运行时。 |
注: 集合的clone,ArrayList 默认实现了cloneable,但是List<A> A对象不是深度克隆,A对象的内容也是使用同一个内存地址,所以A对象也必须实现clone
转载至:https://www.cnblogs.com/lemon-flm/p/9565695.html
原型模式 —— Java的赋值、浅克隆和深度克隆的区别的更多相关文章
- Java的赋值、浅克隆和深度克隆的区别
赋值 直接 = ,克隆 clone 假如说你想复制一个简单变量.很简单: int a= 5; int b= a; b = 6; 这样 a == 5, b == 6 不仅仅是int类型,其它七种原始数 ...
- 如何复制一个java对象(浅克隆与深度克隆)
在项目中,有时候有一些比较重要的对象经常被当作参数传来传去,和C语言的值传递不同,java语言的传递都是引用传递,在任何一个地方修改了这个对象的值,就会导致这个对象在内存中的值被彻底改变.但是很多时候 ...
- 设计模式之第9章-原型模式(Java实现)
设计模式之第9章-原型模式(Java实现) “快到春节了,终于快放假了,天天上班好累的说.”“确实啊,最近加班比较严重,项目快到交付了啊.”“话说一到过节,就收到铺天盖地的短信轰炸,你说发短信就发吧, ...
- 原型模式--java代码实现
原型模式 原型模式,属于对象创建型模式中的一种.通过复制原型对象的方法来创建一个对象实例,且该对象与原对象有相同的数据结构和值.类似我们在备份数据库信息的时候,将数据库中表的结构和数据的一同备份,生成 ...
- 设计模式之原型模式——Java语言描述
原型模式是用于创建重复对象,同时又能保证性能.这种类型的设计模式属于创建型模式,它提供了一种创建对象的方式 这种模式实现了一个原型接口,该接口用于创建当前对象的克隆.当直接创建对象的代价比较大时,则适 ...
- PrototypePattern(原型模式)-----Java/.Net
原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式.
- Java clone() 浅克隆与深度克隆(转)
以下文字转自:桔子园 http://www.blogjava.net/orangelizq/archive/2007/10/17/153573.html 现在Clone已经不是一个新鲜词语了,伴随着“ ...
- Java clone() 浅克隆与深度克隆
内容转自:http://www.blogjava.net/orangelizq/archive/2007/10/17/153573.html 现在Clone已经不是一个新鲜词语了,伴随着“多莉”的产生 ...
- 深度分析:java设计模式中的原型模式,看完就没有说不懂的
前言 原型模式(Prototype模式)是指:用原型实例指定创建对象的种类,并且通过拷贝这些原型,创建新的对象 原型模式是一种创建型设计模式,允许一个对象再创建另外一个可定制的对象,无需知道如何创建的 ...
随机推荐
- ES6之主要知识点(一)
引自:http://es6.ruanyifeng.com let 块级作用域 const 1.let let声明的变量只在它所在的代码块有效. for循环的计数器,就很合适使用let命令. var a ...
- 使用XPath查询带有命名空间(有xmlns)的XML(转)
使用XPath查询带有命名空间(有xmlns)的XML 标签: xmlsilverlightwebserviceencodingwpfinclude 2012-06-19 10:26 3235人阅读 ...
- JZOJ[5971]【北大2019冬令营模拟12.1】 party(1s,256MB)
题目 题目大意 给你一棵树,在树上的某一些节点上面有人,要用最小的步数和,使得这些人靠在一起.所谓靠在一起,即是任意两个人之间的路径上没有空的节点(也就是连在一起). N≤200N \leq 200N ...
- Spring_关于@Resource注入为null解决办法
初学spring,我在dao层初始化c3p0的时候,使用@Resource注解新建对象是发现注入为null,告诉我 java.lang.NullPointerException. @Repositor ...
- Java 容易疑惑的一些杂记录
1 final.finally和finalize final 是一个关键字 ,final 修饰 对象不能被修改,final 修饰的方法不能被重写,final 修饰的 类 不能被继承. finally ...
- 简单的选项卡制作(原生JS)
<!doctype html> <html> <head> <meta charset="utf-8"> <title> ...
- PAT甲级——A1026 Table Tennis
A table tennis club has N tables available to the public. The tables are numbered from 1 to N. For a ...
- spring基于接口的代理报错
报错: 1.在service层加上@Transactional注解.浏览器端报错(如下),eclipse控制台无信息 2.去掉@Transactional注解,无报错,但是数据库没有信息插入. 解决方 ...
- 关于UML类图的一点理解(转)
首先我们定义一个非常简单的Person类,代码如下: public class Person { private String name; private int age =1; public Str ...
- Pandas怎样按条件删除行?
来自: https://stackoverflow.com/questions/13851535/delete-rows-from-a-pandas-dataframe-based-on-a-cond ...