这篇文章来源于《java面试宝典》抱歉忘了引用地址:想发布为引用文章的,但是没有引用地址这个必填项,暂且作为原创吧,毕竟里面的部分文字和代码自己敲的;
1、Clone
在编程中我们会遇到这种情况,目前:有一个对象A已经有许多有效的数值,此时我们需要对象B 和A一致,并且对B的以后的修改不影响A的值,就是A与B是两个独立的值,但是B的初始值是A,clone就是实现这种操作最简单的方法:
就像:copy一份文件夹,一模一样的,对copy版本的操作不影响原版的数据;
2、new 一个对象与Clone的区别:
new操作就是分配内存。程序执行到new操作时,首先去看new操作后的类型,确定需要分配多大的内存空间。分配完成内存后,调用构造函数,填充对象的各个域,这是初始化,然后一个对象创建完毕,将引用地址发布到外部就可以使用这个对象;
clone的操作第一步也是分配内存,调用clone方法时,分配的内存与原对象相同,然后再使用原对象的对象中各个域中的数据填充新的对象域,填充完毕后但会被创建的对象,把对象的引用地址发布到外部就可以使用这个对象;
3、clone的对象的使用:
public class CloneTest {
public static void main(String[] args) throws CloneNotSupportedException {
//-------------------复制引用-----------------
Person p1=new Person("zhang", 23);
Person p2=p1;
System.out.println(p1);
System.out.println(p2);
/**
* result:org.pbccrc.org.pbccrc.Person@15db9742
org.pbccrc.org.pbccrc.Person@15db9742
复制引用是同一个对象
*/
//----------------------Clone---------------------------------
Person p3=new Person("zhang", 23);
Person p4=(Person) p3.clone();
System.out.println(p3);
System.out.println(p4);
/**
* result:org.pbccrc.org.pbccrc.Person@6d06d69c
org.pbccrc.org.pbccrc.Person@7852e922
Clone:是不同的对象
*/
}
}
复制引用
复制对象
4、深拷贝与浅拷贝
public class Person implements Cloneable {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return (Person)super.clone();
}
}
在clone时由于 age 是基本数据类型,直接将一个 4 字节的整数值拷贝过来就行。但是 name 是 String 类型的, 它只是一个引用, 指向一个真正的 String 对象,那么对它的拷贝有两种方式: 直接将原对象中 的 name 的引用值拷贝给新对象的 name 字段, 或者是根据原 Person 对象中的 name 指向的字符串对象创建一个 新的相同的字符串对象,将这个新字符串对象的引用赋给新拷贝的 Person 对象的 name 字段。
//----------------------Clone---------------------------------
Person p3=new Person("zhang", 23);
Person p4=(Person) p3.clone();
System.out.println(p3);
System.out.println(p4);
/**
* result:org.pbccrc.org.pbccrc.Person@6d06d69c
org.pbccrc.org.pbccrc.Person@7852e922
Clone:是不同的对象
*/
//----------------验证是否深浅拷贝----------
String result=p3.getName()==p4.getName()?"String类型的 name浅拷贝":"String类型的 name深拷贝";
System.out.println(result);
String类型的 name浅拷贝
注:对于对象中的引用类型调用Clone方法,其实是浅拷贝
5、实现深拷贝
实现一个对象的深拷贝需要:
1、需要深拷贝的对象实现Cloneable接口;
2、重写其中的clone方法,调用clone方法时需要将对象中引用类型对象clone一份;
3、对象中的引用类型实现cloneable接口并重写clone方法;
public class CloneTest2 {
public static void main(String[] args) throws CloneNotSupportedException {
Body body=new Body(new Head(new Face()));
Body body1 = (Body) body.clone();
System.out.println("body == body1 : " + (body == body1) );
System.out.println("body.head == body1.head : " + (body.head == body1.head));
}
static class Body implements Cloneable{
private Head head;
public Body(Head head) {
super();
this.head = head;
}
@Override
protected Object clone() throws CloneNotSupportedException {
Body body= (Body) super.clone();
body.head=(Head) head.clone();
return body;
}
}
static class Head implements Cloneable{
private Face face;
public Head(Face face) {
super();
this.face = face;
}
@Override
protected Object clone() throws CloneNotSupportedException {
Head head=(Head) super.clone();
head.face=(Face)face.clone();
return head;
}
}
static class Face implements Cloneable{
public Face() {
super();
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
}
result:
body == body1 : false
body.head == body1.head : false