当你将一个对象的引用作为参数传到一个方法中,而这个方法可能会改变该引用所指对象的属性,但你不想让这种事情发生,此时java的克隆技术能帮到你。下面就来讨论一下,如何让你的类具有可克隆的能力,怎样才能做到深层拷贝。
虽然Object类定义了clone()方法,但并不是每个class天生都具有克隆能力,要想使你的类具有克隆能力,有三件事儿你必须要做:
1、实现Cloneable接口。
2、覆盖clone()方法,并把其访问属性改为public的,否则只能在同包中的类或子类中访问,因为Object的clone()方法是protected的。
3、在clone()方法中调用super.clone()方法。
package scjp.cloning;
public class Cloing02 {
public static void main(String[] args) {
MyObject obj1 = new MyObject("eric",24);
MyObject obj2 = null;
try {
obj2 = (MyObject)obj1.clone();//obj2是obj1的克隆,此时它们的内容一样,但它们是两个独立的对象。
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
//对obj2对象属性的更改不会影响到obj1
obj2.setAge(25);
obj2.setName("lth");
System.out.println(obj1.getName()); //eric
System.out.println(obj1.getAge()); //24
System.out.println(obj2.getName()); //lth
System.out.println(obj2.getAge()); //25
}
}
class MySuperObject{
String name;
public MySuperObject(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
//1、实现Cloneable接口
class MyObject extends MySuperObject implements Cloneable{
int age;
public MyObject(String name,int age) {
super(name);
this.age = age;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//2、覆盖clone()方法。
//如果没有实现Cloneable接口的话,clone()方法会抛出CloneNotSupportedException异常。
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone(); //3、调用super.clone()
}
}
深层拷贝
上面的例子可以看出,被克隆的类的属性都属于基本类型,所以牵涉不到深层拷贝的问题。但如果被克隆的类是一个组合类(其它类的对象作为成员属性)再用上面的方法就只能做到浅层拷贝即对象成员仍指向本体的对象成员。要想做到深层拷贝需在覆盖clone()方法时下点工夫。
package scjp.cloning;
public class Cloning03 {
public static void main(String[] args) {
ClassRoom classRoom = new ClassRoom();
ClassRoom classRoom2 = null;
try {
classRoom2 = (ClassRoom)classRoom.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
//更改classRoom2对象的成员属性,不会对classRoom造成影响。
classRoom2.teacher.name = "Tom";
for(int i = 0;i < classRoom2.students.length;i++){
classRoom2.students[i].name = "stu"+i;
classRoom2.desks[i].hight = 300;
classRoom2.desks[i].width = 400;
}
System.out.println(classRoom);
System.out.println(classRoom2);
}
}
class Student implements Cloneable{
String name;
public Student(String name) {
this.name = name;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class Teacher implements Cloneable{
String name;
public Teacher(String name) {
this.name = name;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class Desk implements Cloneable{
int hight;
int width;
public Desk(int hight,int width) {
this.hight = hight;
this.width = width;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class ClassRoom implements Cloneable{
//每个成员都要实现Cloneable接口。
Teacher teacher;
Student[] students;
Desk[] desks;
public ClassRoom() {
this.teacher = new Teacher("Eric");
this.students = new Student[10];
this.desks = new Desk[10];
for(int i = 0;i < this.students.length;i++){
this.students[i] = new Student("student"+i);
this.desks[i] = new Desk(200,300);
}
}
@Override
protected Object clone() throws CloneNotSupportedException {
ClassRoom classRoom = null;
classRoom = (ClassRoom)super.clone();
//每一个成员都要克隆
classRoom.teacher = (Teacher)classRoom.teacher.clone();
classRoom.students = classRoom.students.clone();
classRoom.desks = classRoom.desks.clone();
//集合中的每一个对象也都要克隆
for(int i = 0;i < classRoom.students.length;i++){
classRoom.students[i] = (Student)classRoom.students[i].clone();
classRoom.desks[i] = (Desk)classRoom.desks[i].clone();
}
return classRoom;
}
@Override
public String toString() {
StringBuilder sbBuilder = new StringBuilder();
sbBuilder.append("Teacher:").append(this.teacher.name).append("\r\n");
sbBuilder.append("Students:");
for(int i = 0;i < this.students.length;i++){
sbBuilder.append(students[i].name);
sbBuilder.append(",");
}
sbBuilder.append("\r\n");
sbBuilder.append("Desk(Hight,Width):");
for(int i = 0;i < this.students.length;i++){
sbBuilder.append("(");
sbBuilder.append(desks[i].hight);
sbBuilder.append(",").append(desks[i].width).append(")");
}
sbBuilder.append("\r\n");
return sbBuilder.toString();
}
}
Teacher:Eric
Students:student0,student1,student2,student3,student4,student5,student6,student7,student8,student9,
Desk(Hight,Width):(200,300)(200,300)(200,300)(200,300)(200,300)(200,300)(200,300)(200,300)(200,300)(200,300)
Teacher:Tom
Students:stu0,stu1,stu2,stu3,stu4,stu5,stu6,stu7,stu8,stu9,
Desk(Hight,Width):(300,400)(300,400)(300,400)(300,400)(300,400)(300,400)(300,400)(300,400)(300,400)(300,400)
继承体系中的克隆
默认情况下你自己写的类是不具有克隆能力的,但当你做完了文章开始时所说的三件事后,你的类便拥有了克隆能力,并且继承自该类的所有子类也都与生具有克隆能力。
分享到:
相关推荐
031111_【第11章:Java常用类库】_对象克隆技术笔记
clone()方法示例(对象克隆)。作者: 初生不惑
一个详细讲解JAVA_对象克隆的例子 希望可以帮助到你。
对象复制工具,基于cglib BeanCopier 实现对实体对象、持久化对象、代理对象的克隆和复制, 避免重复克隆和复制,避免无限循环引用,(校验hashCode) 可指定实体对象和集合属性的克隆深度
计算机前端-核心编程.视频07对象克隆.avi
主要介绍了Java编程实现对象克隆(复制)代码详解,涉及了克隆的原因,如何实现克隆,克隆的一般步骤,深克隆与浅克隆的介绍等相关内容,具有一定借鉴价值,需要的朋友可以参考下。
Java对象的复制与克隆,包含浅复制和深层复制。 免费下载啦,绝对值得一看。
java的两种深度克隆方法,1cloneTest是用Cloneable接口的clone方法实现(对象必须要实现cloneable接口).2cloneSerialize.java是用对象流写对象到byte数组中,然后从byte数组中取得对象.(对象必须要实现serializble接口)
对象的克隆操作过程,展示了对象中数据字段是如何是实现克隆的
1.对象克隆 clone PHP4面向对象功能一个很大的缺点,是将对象视为另一种数据类型,这使得很多常见的OOP方法无法使用,如设计模式。这些方法依赖于将对象作为引用传递给其他类方法,而不是作为值传递,而按值传递却是...
查看了很多文章对于clone()方法讲解都不慎透彻,特别是对于深层克隆的讲解语言晦涩难懂,很难理解,包括Oracle公司出版的JDK帮助文档也讲的不清楚,本人通过具体实践通过浅显易懂的语言详细讲解了clone()方法。...
本文实例讲述了PHP对象克隆clone用法。分享给大家供大家参考,具体如下: 浅克隆:只是克隆对象中的非对象非资源数据,即对象中属性存储的是对象类型,则会出现克隆不完全 <?php class B{ public $val = 10; } ...
主要介绍了php实现对象克隆的方法,实例分析了php对象实例化与克隆的使用技巧,需要的朋友可以参考下
java 深克隆浅克隆···············
对象克隆ES5的深克隆和比较概要// just for conveniencevar log = function ( ) { console . log . apply ( console , [ ] . slice . call ( arguments ) ) } ; var src = { name : 'dankogai' , lang : [ 'perl' ] ...
php5 类与对象 个人总结与简单的例子,... PHP 对象克隆 clone 关键字与 __clone() 方法 17. PHP 对象的存储与传输(序列化 serialize 对象) 18. php 设计模式:工厂模式和单例模式 19.对象对象迭代 20 this关键字