深拷贝、浅拷贝与Cloneable接口
深拷贝与浅拷贝
浅拷贝
public class Student implements Cloneable{
Integer a;
Integer b;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
String c;
Student child;
}
public class Main {
public static void main(String[] args) throws CloneNotSupportedException {
Student s = new Student();
Student s2 = (Student) s.clone();
System.out.println(s == s2);
System.out.println(s.child == s2.child);
}
}
/**********************************************************************/
false
true
由上述代码及运行结果我们可以看出,调用clone方法之后,确实s2是一个新的对象,内存地址已经发生了改变,但s和s2的child属性仍然指向相同的地址,这便是浅拷贝,当然8种基本数据类型是深拷贝,String则是例外。
深拷贝
public class Teacher implements Cloneable{
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class Student implements Cloneable{
Integer a;
Integer b;
public Student(Teacher t) {
this.t = t;
}
@Override
protected Object clone() throws CloneNotSupportedException {
Student s = (Student) super.clone();
s.t = (Teacher)s.t.clone();//彻底深拷贝关键
return s;
}
String c;
Teacher t;
}
public class IntersectionofTwoArraysII {
public static void main(String[] args) throws CloneNotSupportedException {
Teacher t = new Teacher();
Student s = new Student(t);
Student s2 = (Student) s.clone();
System.out.println(s == s2);
System.out.println(s.t == s2.t);
}
}
/**********************************************************************/
false
false
如上代码运行结果所示为深拷贝,想要实现深拷贝,就需要在重写Cloneable接口的clone()方法,并调用属性的clone()方法,因此关联类也要实现Cloneable接口,从而形成拷贝链,实现彻底深拷贝。
实现彻底的深拷贝并不容易,因为它要求涉及的所有类都实现了cloneable接口,但是如StringBuffer由于其没有实现Cloneable接口,想要实现深拷贝效果,则需要做特殊处理从而实现深拷贝的效果。可以在clone方法中实现
sb=new StringBuffer(sb.toString());
Cloneable接口
Cloneable其实就是一个标记接口,只有实现这个接口后,然后在类中重写Object中的clone方法,然后通过类调用clone方法才能克隆成功,如果不实现Cloneable其实就是一个标记接口接口,调用clone方法则会抛出CloneNotSupportedException(克隆不被支持)异常。
如何判断类是否实现了cloneable接口呢?
/**
* Creates and returns a copy of this {@code Object}. The default
* implementation returns a so-called "shallow" copy: It creates a new
* instance of the same class and then copies the field values (including
* object references) from this instance to the new instance. A "deep" copy,
* in contrast, would also recursively clone nested objects. A subclass that
* needs to implement this kind of cloning should call {@code super.clone()}
* to create the new instance and then create deep copies of the nested,
* mutable objects.
*
* @return a copy of this object.
* @throws CloneNotSupportedException
* if this object's class does not implement the {@code
* Cloneable} interface.
*/
protected Object clone() throws CloneNotSupportedException {
if (!(this instanceof Cloneable)) {
throw new CloneNotSupportedException("Class doesn't implement Cloneable");
}
return internalClone((Cloneable) this);
}
/*
* Native helper method for cloning.
*/
private native Object internalClone(Cloneable o);
clone方法首先会判对象是否实现了Cloneable接口,若无则抛出CloneNotSupportedException, 最后会调用internalClone. intervalClone是一个native方法,一般来说native方法的执行效率高于非native方法。
参考资料
深拷贝、浅拷贝与Cloneable接口的更多相关文章
- Java 深拷贝、浅拷贝及Cloneable接口
Cloneable接口是一个空接口,仅用于标记对象,Cloneable接口里面是没有clone()方法,的clone()方法是Object类里面的方法!默认实现是一个Native方法 protecte ...
- 001 Java 深拷贝、浅拷贝及Cloneable接口
原本写过,后来在阅读的时候,感觉自己都不是太明白了,删除后参考人家的又重新写了一份. 一:开篇 1.复制一个变量 举例是int类型. 其他其中七种原始数据类型同样适用. 原始类型:boolean,ch ...
- Java中的Cloneable接口与深拷贝、浅拷贝
Cloneable接口是一个标记接口,也就是没有任何内容,定义如下: 这里分析一下这个接口的用法,clone方法是在Object种定义的,而且是protected型的,只有实现了这个接口,才可以在该类 ...
- java 的对象拷贝(有深浅拷贝两种方式,深拷贝实现的两种方式(逐层实现cloneable接口,序列化的方式来实现))
Java提高篇--对象克隆(复制)(转自:http://www.cnblogs.com/Qian123/p/5710533.html#_label0) 阅读目录 为什么要克隆? 如何实现克隆 浅克 ...
- Java的一个高性能快速深拷贝方法。Cloneable?
本人在设计数据库缓存层的时候,需要对数据进行深拷贝,这样用户操作的数据对象就是不共享的. 这个思路实际上和Erlang类似,就是用数据不共享解决并发问题. 1. 序列化? 原来的做法,是用序列化,我用 ...
- clone 深拷贝 浅拷贝
1. 定义:知道一个对象,但不知道类,想要得到该对象相同的一个副本,在修改该对象的属性时,副本属性不修改,clone的是对象的属性 2. 意义:当一个对象里很多属性,想要得到一个相同的对象,还有set ...
- Java深拷贝浅拷贝
首先,Java中常用的拷贝操作有三个,operator = .拷贝构造函数 和 clone()方法.由于Java不支持运算符重载,我们无法在自己的自定义类型中定义operator=.拷贝构造函数大家应 ...
- Java中的Cloneable接口理解
Cloneable接口是一个标记接口,也就是没有任何内容,定义如下: 这里分析一下这个接口的用法,clone方法是在Object种定义的,而且是protected型的,只有实现了这个接口,才可以在该类 ...
- Java 深拷贝浅拷贝 与 序列化
一.浅拷贝.深拷贝 浅拷贝会对对象中的成员变量进行拷贝:如果是基本类型,拷贝的就是基本类型的值:如果属性是内存地址(引用类型),拷贝的就是内存地址 : 深拷贝,除了基本类型外,引用类型所引用的对象也会 ...
随机推荐
- 透过源码分析ArrayList运作原理
List接口的主要实现类ArrayList,是线程不安全的,执行效率高:底层基于Object[] elementData 实现,是一个动态数组,它的容量能动态增加和减少.可以通过元素下标访问对象,使用 ...
- STM32CubeMX工程定时器配置
STM32CubeMX生成工程 选择自己的芯片型号 配置RCC寄存器时钟为外部晶振 单击芯片配置GPIO,选择输出方式,重命名标签等 进入时钟配置,本人使用的为8M外部晶振作为时钟源,PLL时钟源选择 ...
- centos 64位安装jpeg-6b
先安装libtool和libtool-ltdl-devel 用find命令查找config.sub和config.guess文件 find / -name config.sub find / -nam ...
- wireshark抓包实战(一),抓包原理
一.什么样的"包"能被wireshark抓住呢? 1.本机 即直接抓取进出本机网卡的流量包.这种情况下,wireshark会绑定本机的一块网卡. 2.集线器 用于抓取流量泛洪,冲突 ...
- Java第十五天,泛型
一.定义 泛型是一种未知的数据类型,即当我们不知道该使用哪种数据类型的时候,可以使用泛型. 泛型的本质是为了 参数化 类型(在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型) ...
- IDEA永久激活码获取
废话少说,直接上地址:http://idea.medeming.com/jet/ *小编还是建议,有家底的程序猿还是直接买正版的号,非正版的很多不便的地方~
- defer使用小结
defer 前言 defer的定义 defer执行的规则 为什么需要defer defer进阶 作为匿名函数 作为函数参数 defer命令执行的时机 defer配合recover 总结 参考 defe ...
- RESTful API设计的点
RESTful API 前言 一直在使用RESTful API,但是好像概念还是很模糊的,总结下使用到的点 设计的规范 协议 API与用户的通信协议,总是使用HTTPs协议. 域名 应该尽量将API部 ...
- 智能指针 unique_ptr
unique_ptr 不共享它的指针.它无法复制到其他 unique_ptr,无法通过值传递到函数,也无法用于需要副本的任何标准模板库 (STL) 算法. 1.不能进行复制构造和赋值操作(unique ...
- 如何使用Swagger-UI在线生成漂亮的接口文档
一.简单介绍 Swagger是一个实现了OpenAPI(OpenAPI Specification)规范的工具集.OpenAPI是Linux基金会的一个项目,试图通过定义一种用来描述API格式或API ...