package Cloneable接口;
class Demo {
private String name;
public Demo() {
name = "张三";
System.out.println("执行构造方法Demo");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class CloneableTest implements Cloneable {
private int id;
private Demo demo;
public CloneableTest(int id, Demo demo) {
this.id = id;
this.demo = demo;
System.out.println("执行构造方法CloneableTest");
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Demo getDemo() {
return demo;
}
public void setDemo(Demo demo) {
this.demo = demo;
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
public static void main(String[] args) {
try {
Demo d = new Demo();
CloneableTest c1 = new CloneableTest(1, d);
CloneableTest c2 = (CloneableTest) c1.clone();
System.out.println("c1和c2的引用相同吗?" + (c1 == c2));
System.out.println("c1和c2的类类型相同吗?" + (c1.getClass() == c2.getClass()));
System.out.println("c1和c2的id相同吗?" + (c1.getId() == c2.getId()));
System.out.println("c1和c2的demo的引用相同吗?" + (c1.getDemo() == c2.getDemo()));
System.out.println("c1和c2的demo中的name的引用相同吗?" + (c1.getDemo().getName() == c2.getDemo().getName()));
/**
* 结果:
* 执行构造方法Demo
* 执行构造方法CloneableTest
* c1和c2的引用相同吗?false
* c1和c2的类类型相同吗?true
* c1和c2的id相同吗?true
* c1和c2的demo的引用相同吗?true
* c1和c2的demo中的name的引用相同吗?true
*/
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
(1)、如果想要使用该方法,除了继承Object类之外,还必须实现Cloneable接口:
(2)、clone是不走构造方法的;
(3)、克隆的对象和原对象是两个不同的对象,其地址指向两个不同的堆地址空间;
(4)、两个对象的getClass是相同的;
(5)、对于基本数据类型,clone的时候是按值传递,对于引用数据类型,clone的时候是复制引用;
综上得出结论:利用Object中的clone方法实现的只是浅克隆(shallow clone);
2、深克隆(deep clone)
1、先将对象序列化,之后再反序列化读取,代码如下:
package Cloneable接口;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
class Demo implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private String name;
public Demo() {
name = "张三";
System.out.println("执行构造方法Demo");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class CloneableTest implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private int id;
private Demo demo;
public CloneableTest(int id, Demo demo) {
this.id = id;
this.demo = demo;
System.out.println("执行构造方法CloneableTest");
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Demo getDemo() {
return demo;
}
public void setDemo(Demo demo) {
this.demo = demo;
}
//深克隆方法
public Object deepClone(){
ObjectOutputStream oos=null;
ObjectInputStream ois=null;
Object readObject=null;
try {
oos=new ObjectOutputStream(new FileOutputStream("E:/深克隆/deepClone.txt"));
oos.writeObject(this);
ois=new ObjectInputStream(new FileInputStream("E:/深克隆/deepClone.txt"));
readObject = ois.readObject();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}finally {
try {
if(ois!=null) {
ois.close();
}
if(oos!=null) {
oos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return readObject;
}
public static void main(String[] args) {
Demo d = new Demo();
CloneableTest c1 = new CloneableTest(1, d);
CloneableTest c2 = (CloneableTest) c1.deepClone();
System.out.println("c1和c2的引用相同吗?" + (c1 == c2));
System.out.println("c1和c2的类类型相同吗?" + (c1.getClass() == c2.getClass()));
System.out.println("c1和c2的id相同吗?" + (c1.getId() == c2.getId()));
System.out.println("c1和c2的demo的引用相同吗?" + (c1.getDemo() == c2.getDemo()));
System.out.println("c1和c2的demo中的name的引用相同吗?" + (c1.getDemo().getName() == c2.getDemo().getName()));
/**
* 结果:
* 执行构造方法Demo
* 执行构造方法CloneableTest
* c1和c2的引用相同吗?false
* c1和c2的类类型相同吗?true
* c1和c2的id相同吗?true
* c1和c2的demo的引用相同吗?false
* c1和c2的demo中的name的引用相同吗?false
*/
}
}
2、调用clone方法先克隆出一个新对象,之后手动给新对象的各项数据域设置值,代码如下:
package Cloneable接口;
class Demo implements Cloneable{
private String name;
public Demo() {
name = "张三";
System.out.println("执行构造方法Demo");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class CloneableTest implements Cloneable{
private int id;
private Demo demo;
public CloneableTest(int id, Demo demo) {
this.id = id;
this.demo = demo;
System.out.println("执行构造方法CloneableTest");
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Demo getDemo() {
return demo;
}
public void setDemo(Demo demo) {
this.demo = demo;
}
//手动实现深克隆
@Override
public Object clone() throws CloneNotSupportedException {
CloneableTest clone = (CloneableTest) super.clone();
clone.id=clone.getId();
clone.demo=(Demo) demo.clone();
String str=new String(clone.demo.getName());
clone.demo.setName(str);
return clone;
}
public static void main(String[] args) {
try {
Demo d = new Demo();
CloneableTest c1 = new CloneableTest(1, d);
CloneableTest c2 = (CloneableTest) c1.clone();
System.out.println("c1和c2的引用相同吗?" + (c1 == c2));
System.out.println("c1和c2的类类型相同吗?" + (c1.getClass() == c2.getClass()));
System.out.println("c1和c2的id相同吗?" + (c1.getId() == c2.getId()));
System.out.println("c1和c2的demo的引用相同吗?" + (c1.getDemo() == c2.getDemo()));
System.out.println("c1和c2的demo中的name的引用相同吗?" + (c1.getDemo().getName() == c2.getDemo().getName()));
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
/**
* 结果:
* 执行构造方法Demo
* 执行构造方法CloneableTest
* c1和c2的引用相同吗?false
* c1和c2的类类型相同吗?true
* c1和c2的id相同吗?true
* c1和c2的demo的引用相同吗?false
* c1和c2的demo中的name的引用相同吗?false
*/
}
}