深拷贝、浅拷贝与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 深拷贝浅拷贝 与 序列化
一.浅拷贝.深拷贝 浅拷贝会对对象中的成员变量进行拷贝:如果是基本类型,拷贝的就是基本类型的值:如果属性是内存地址(引用类型),拷贝的就是内存地址 : 深拷贝,除了基本类型外,引用类型所引用的对象也会 ...
随机推荐
- Redis对象——列表(List)
列表(list)类型是用来存储多个有序的字符串,列表中的每个字符串称为元素(element),一个列表最多可以存储232-1个元素.在Redis中,可以对列表两端插入(push)和弹出(pop),还可 ...
- Appium自动化(2) - appium环境安装常见问题的解决方案
如果你还想从头学起Appium,可以看看这个系列的文章哦! https://www.cnblogs.com/poloyy/category/1693896.html 问题1:adb检测不到设备 解决 ...
- php连接数据库,php连接mysql并查询的几种方式,PHP PDO连接以及预处理
PHP连接数据库 面向过程 $config = [ 'host'=>'127.0.0.1', //数据库地址 'name'=>'test', //库名 'user'=>'root', ...
- linux下shell脚本中sed命令的用法
先来给一个案例: #将old.sql文件中的符号“|”替换为“,”,并保存到test.sql文件中 sed "s/|/,/g" "old.sql"> te ...
- PHP的运行方式(SAPI)
PHP 常量 PHP_SAPI 具有和 php_sapi_name() 相同的值. define('IS_CGI',(0 === strpos(PHP_SAPI,'cgi') || false !== ...
- 测试老司机都在用的表白神器你会吗?-Fiddler之AutoResponse线上调试
一.Fiddler在线调试功能和表白神器介绍 在以往的工作中,线上有bug,就需要把文件弄到本地来改,但经常会碰见本地环境又和线上不一样,导致调试困难,闭着眼睛改好之后传到线上去看对不对,不对的话 ...
- 家庭记账本app实现登录注册界面以及仿微信操作界面(共4个实现一个)遇到了麻烦
今天学习了数据的创建,以及关于数据库的相关操作. 今天主要是实现了对于数据库的增加和查找. 具体的代码如下: 首先是数据库的创建: DBOpenMessage.java package com.exa ...
- Flask 入门(一)(Mac 系统)
熟话说,万事开头难,为了运行这第一个程序,我可是碰了不少壁,接下来我将正确的方法交给大家. 1.首先得有python和虚拟环境 (1)python环境苹果系统自带 (2)虚拟环境: 安装virtual ...
- 切片-list、字符串
切片-list.字符串 1.字符串,切片顾头不顾尾 s="123455" print(s[0:3]) 结果:123 2.list d=[12,34,45] print(d[: ...
- 文档根元素 "beans" 必须匹配 DOCTYPE 根 "null"
文档根元素 "beans" 必须匹配 DOCTYPE 根 "null" (2011-11-20 21:26:41) 转载▼ 标签: 杂谈 分类: spring- ...