克隆:就是复制一个对象的复本.若只需要复制对象的字段值(对于基本数据类型,如:int,long,float等,则复制值;对于复合数据类型仅复制该字段值,如数组变量则复制地址,对于对象变量则复制对象的引用。)
如果对象中引用了其他对象,一般克隆后会导致引用对象的内容改变。
浅拷贝:使用clone()即为浅拷贝,默认的拷贝方式是复制一个新的原对象,并赋予原对象相同的全局对象的值和引用。即原对象和复制对象的全局引用变量指向的是一个相同的对象空间。
深拷贝:需要自己实现,即将原对象中的全局引用变量指向的对象也复制一份放入复制对象中。
浅拷贝
1、类实现 Cloneable 接口
2、类中重写clone方法
public Object clone(){
Object o=null;
try {
o=super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return o;
}
深拷贝:
方法一:当前类和引用来的类都实现cloneable接口,和重写clone方法。实现引用的拷贝。
如下
public class Student implements Cloneable {
private String name;
private int age;
private Professor pro;
public Student(){}
public Student(String name,int age,Professor pro){
this.name=name;
this.age=age;
this.pro=pro;
}
//实现clone()方法
public Object clone(){
Object o=null;
try {
o=super.clone();
} catch (CloneNotSupportedException e) {
System.out.println(e.toString());
}
pro=(Professor)pro.clone();
return o;
}
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;
}
public Professor getPro() {
return pro;
}
public void setPro(Professor pro) {
this.pro = pro;
}
public static void main(String[] args) {
Professor p=new Professor("wangwu",50);
Student s1=new Student("zhangsan",18,p);
Student s2=(Student)s1.clone();
s2.getPro().setName("maer");
s2.getPro().setAge(40);
System.out.println("name="+s1.getPro().getName()
+",age="+s1.getPro().getAge());
//name=maer,age=40
}
}
//被引用的对象类
public class Professor implements Cloneable{
private String name;
private int age;
public Professor(){}
public Professor(String name,int age){
this.name=name;
this.age=age;
}
public Object clone(){
Object o=null;
try {
o=super.clone();
} catch (CloneNotSupportedException e) {
System.out.println(e.toString());
}
return o;
}
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;
}
}
实现了引用对象的拷贝。
方法二:实现Serializable接口,实现对象拷贝到流中,从流中读取对象。
1、舍弃cloneable接口和clone方法。
2、类实现Serializable接口,并实现如下克隆工具类
public class IOUtils {
//实现深度克隆方法
@SuppressWarnings("unchecked")
public static <T extends Serializable> T clone(T obj) throws Exception {
//写入流
ByteArrayOutputStream bout = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bout);
oos.writeObject(obj);
//从流中读出对象
ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bin);
return (T) ois.readObject();
}
}
Student 类中的main方法变成如下:
public static void main(String[] args) {
Professor p=new Professor("wangwu",50);
Student2 s1=new Student2("zhangsan",18,p);
Student2 s2=new Student2();
try {
s2 = IOUtils.clone(s1);//clone方法
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
s2.getPro().setName("maer");
s2.getPro().setAge(40);
System.out.println("name="+s1.getPro().getName()
+",age="+s1.getPro().getAge());
}
以上;