Java clone
来源:互联网 发布:淘宝网自助开通在哪里 编辑:程序博客网 时间:2024/06/04 01:17
参考:
java.lang Interface Cloneable
java.lang Class Object
下面学习 Java
中的 Object.clone()
方法 和 cloneable
接口的概念和使用,学习关于 强复制(克隆,拷贝)和浅复制 的区别和联系
主要内容:
Object.clone()
方法和cloneable
接口Object.clone()
方法的实现- 深复制和浅复制
Object.clone()
方法和 cloneable
接口
Object.clone()
方法和 cloneable
接口参考:java.lang Class Object
Object.clone()
方法
Object
类是 Java
中类层次结构的根,是所有类的超类。新建一个类,如果没有继承超类,Java
默认使用 Object
类作为该类的超类
Object.clone()
方法格式如下:
protected native Object clone() throws CloneNotSupportedException;
功能:创建并返回复制对象
Cloneable
接口
Cloneable
接口没有任何方法,它仅用于表明类想要重载 Object.clone()
方法。如果没有继承该接口就重载 Object.clone()
方法,Object.clone()
方法将抛出 java.lang.CloneNotSupportedException
异常
Object.clone() 方法的实现
创建新类 Cloner
,继承接口 Cloneable
,并重载 clone
方法
import java.util.Arrays;/** * Created by zj on 2017/10/16. */public class Cloner implements Cloneable { private int num; private String str; private Person person; public Cloner(int num, String str, Person person) { this.num = num; this.str = str; this.person = person; } public void setNum(int num) { this.num = num; } public void setStr(String str) { this.str = str; } public void setName(String name) { this.person.setName(name); } public void setAge(int age) { this.person.setAge(age); } @Override public String toString() { return "Cloner{" + "num=" + num + ", str='" + str + '\'' + ", person=" + person + '}'; } // @Override// protected Object clone() throws CloneNotSupportedException {// return super.clone();// } @Override protected Object clone() { Cloner cloner = null; try { cloner = (Cloner) super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return cloner; } static class Person { String name; int age; public Person(String name, int age) { this.name = name; this.age = age; } public void setName(String name) { this.name = name; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; } }}
重载方法 clone()
,调用超类的 clone()
方法即可实现对象复制,因为 clone()
方法会抛出检查时异常 CloneNotSupportedException
,所以修改代码如上所示
测试代码如下:
public static void main(String[] args) throws CloneNotSupportedException { int num = 10; String str = "str"; Person person = new Person("zj", 1111); Cloner src = new Cloner(10, "str", person); Cloner dst = (Cloner) src.clone(); System.out.println("Before..."); System.out.println(src); System.out.println(dst); dst.setNum(20); dst.setStr("str2"); dst.setName("name"); dst.setAge(100); System.out.println("After..."); System.out.println(src); System.out.println(dst); }
问题:创建一个类 Cloner
的实例 src
,并得到它的克隆对象 dst
,修改 dst
的值,发现 src
的部分属性也发生了变化
深复制和浅复制
参考:
java clone()机制
使用 clone()
方法进行对象的复制,就是在堆上新建一个和原先对象同样大小的存储空间,将原先对象的内容复制到该存储空间
优点如下:
- 操作简单:仅需重载
clone()
方法即可 - 执行效率高:如果使用
new
关键字重新建一个对象,然后进行属性的复制,需要耗费大量的操作
缺点如下:
如果仅执行 super.clone()
方法进行复制,对复制对象的操作有可能会改变原先对象的属性
原始类型(primitive type)
参考:
Java的原始类型(Primitive Type)
Java
的原始类型就是指基本数据类型,即
byte
char
short
int
long
float
double
boolean
可变(mutable
),不可变(immutable
)对象
参考:
如何创建不可变(Immutable)的Java类或对象
Java中mutable对象和immutable对象的区别
不可变对象指对象被创建后无法改变状态的对象,即每次对它进行操作都是产生了新的对象,如 String
而可变对象与之相反,对象在创建后,可以在本身发送改变,如 StringBuffer
浅复制
直接使用 Object.clone()
方法进行复制的操作属于浅复制
即如果该对象内部包含了对可变对象的引用,那么复制得到的新对象同样拥有对该可变对象的引用,所以在新对象中进行可变对象的操作后,原对象的属性也发生了变化
深复制
如果复制得到的对象的操作不会影响到原对象,那么这种操作就是深复制
为实现深复制,需要在重载 clone()
方法的时候对可变对象创建新的地址空间,
上面代码修改如下:
@Overrideprotected Object clone() { Cloner cloner = null; try { cloner = (Cloner) super.clone(); cloner.person = new Person(this.person.name, this.person.age); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return cloner;}
重新测试,结果如下:
- java clone
- java clone
- java clone
- java clone
- java clone
- Java clone
- Java clone
- Java Clone
- java clone
- JAVA clone
- Java clone
- Java Clone
- java clone
- Java clone
- 【Java】clone()
- Java Clone
- java clone
- Java clone()
- 51入门基础知识储备---ROM与RAM:计算机中的2种存储器
- C++11多线程互斥锁的使用
- python高效编程技巧6(如何实现用户的历史记录功能)
- 【BZOJ】1087 [SCOI2005]互不侵犯King 状压DP
- activeMQ优点与和spring整合的xml配置
- Java clone
- 写函数去除字符串中包含的非字母字符(不包括空格),将小写字母转换成大写字母
- SpringBoot JPA 条件分页
- python高效编程技巧7(pickle的使用:可以将一个对象存储在一个文件中,或者load进来)
- SD卡规范解读
- Gym 101246.G
- ACM刷题狗的心路历程1
- 周志华机器学习第二章习题
- 素数分解