您的位置:首页 > 编程语言 > Java开发

java Clone

2013-09-26 11:13 441 查看
一、    浅复制与深复制概念
1)    
浅复制:原对象和克隆后的对象的属性值是一样的,原对象的属性对象和克隆后的属性对象指向的是同一个引用。
2)    
深复制:原对象和克隆后的对象的成员属性中属性类型是基本数据类型和String的成员属性值是一样的,原对象的属性对象和克隆后的属性对象指向的是则是不同的引用,即克隆后的属性对象会指向堆中新的对象。
二、    总结
1)    
浅复制的类只需要实现Cloneable接口实现。
2)    
深度复制的类中成员属性如果有自定义的引用数据类型时,那么自定义的类也需要实现Cloneable接口才行。
3)    
深度复制时如果类的成员属性是List、Map时,仅仅实现Cloneable接口这些成员属性是做不到深度复制的,如果要实现深度复制则需要重新new。
4)    
通过序列化实现的深度复制是真正的深度复制,所有的引用对象都会是重新new出来的拷贝,不会影响原对象。
三、    代码案例
1) 浅复制:
package clone.easy;
 
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
 
publicclass Teacher {
    private String
name;
 
    privateintage;
 
    public String getName() {
        returnname;
    }
 
    publicvoid setName(String name) {
        this.name = name;
    }
 
    publicint getAge() {
        returnage;
    }
 
    publicvoid setAge(int
age) {
        this.age = age;
    }
   
    @Override
    public String toString() {
        return ToStringBuilder.reflectionToString(this,
ToStringStyle.MULTI_LINE_STYLE);
       }
    }
 
    package clone.easy;
 
import java.util.ArrayList;
import java.util.List;
 
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
/**
 * 
浅复制(浅克隆)
 * 
被复制对象的所有变量都含有与原来的对象相同的值,
 * 
而所有的对其他对象的引用仍然指向原来的对象。
 * 
换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象。
 *@author13061494
 *
 */
publicclass Student
implements Cloneable {
    private String
name;
 
    privateintage;
 
    private List<String>
list =
new ArrayList<String>();
   
    private Teacher
teacher;
 
    public Object clone() {
        System.out.println("clone");
        Object o = null;
        try {
            o = (Student)
super
.clone();// Object
中的clone()识别出你要复制的是哪一个对象。
        } catch (CloneNotSupportedException e) {
            System.out.println(e.toString());
        }
 
        return o;
    }
 
    publicstaticvoid main(String[] args)
throws Exception {
        Student student =
new
Student();
        Teacher teacher =
new
Teacher();
        teacher.setName("teacher");
        teacher.setAge(20);
        student.teacher = teacher;
        student.name =
"gx";
        student.age = 15;
        student.list.add("list");
        Student
clone = (Student) student.clone();
        clone.name =
"cm";
        clone.teacher.setName("clone Teacher");
        clone.list.add("clone list");
        System.out.println(clone);
        System.out.println(student);
    }
 
    @Override
    public String toString() {
        return ToStringBuilder.reflectionToString(this,
ToStringStyle.MULTI_LINE_STYLE);
    }
}
 
运行结果:
clone
clone.easy.Student@6d8e6d8e[
  name=cm
  age=15
  list=[list, clone list]
  teacher=clone.easy.Teacher@35fd35fd[
  name=clone Teacher
  age=20
]
]
clone.easy.Student@33533353[
  name=gx
  age=15
  list=[list, clone list]
  teacher=clone.easy.Teacher@35fd35fd[
  name=clone Teacher
  age=20
]
]
 
2) 深度复制
    package clone.deep;
 
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
 
publicclass Teacher
implements Cloneable{
    private String
name;
 
    privateintage;
 
    public String getName() {
        returnname;
    }
 
    publicvoid setName(String name) {
        this.name = name;
    }
 
    publicint getAge() {
        returnage;
    }
 
    publicvoid setAge(int
age) {
        this.age = age;
    }
   
    @Override
    protected Object clone()
throws CloneNotSupportedException {
        //
TODO Auto-generated method stub
        returnsuper.clone();
    }
   
    @Override
    public String toString() {
        return ToStringBuilder.reflectionToString(this,
ToStringStyle.<
15e4e
em>MULTI_LINE_STYLE);
    }
}
 
package clone.deep;
 
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
 
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
 
/**
 *深复制(深克隆)
 *被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。
 *那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。
 *换言之,深复制把要复制的对象所引用的对象都复制了一遍
 *@author13061494
 *
 */
publicclass Student
implements Cloneable {
    private String
name;
 
    privateintage;
 
    private Teacher
teacher;
   
    private List<String>
list;
   
    private List<String>
newList =
new ArrayList<String>();
   
    private Map<String, String>
map =
new HashMap<String, String>();
   
    public Object clone()
throws CloneNotSupportedException{
        System.out.println("clone");
        Student o = null;
        o = (Student) super.clone();// Object
中的clone()识别出你要复制的是哪一个对象。
        o.teacher = (Teacher)teacher.clone();
        return o;
    }
 
    publicstaticvoid main(String[] args)
throws CloneNotSupportedException {
        Student student =
new
Student();
        Teacher teacher =
new
Teacher();
        teacher.setName("teacher");
        teacher.setAge(20);
        student.teacher = teacher;
        student.name =
"gx";
        student.age = 15;
       
        List<String> list =
new
ArrayList<String>();
        list.add("list");
        student.list = list;
       
        student.newList.add("newList");
       
        student.map.put("map",
"map");
       
        Student clone = (Student) student.clone();
        clone.name =
"cm";
        clone.teacher.setName("clone Teacher");
        clone.list.add("clone list");
        clone.newList.add("clone newList");
        clone.map.put("clone map",
"clone map");
        System.out.println(clone);
        System.out.println(student);
    }
 
    @Override
    public String toString() {
        return ToStringBuilder.reflectionToString(this,
ToStringStyle.MULTI_LINE_STYLE);
    }
}
 
运行结果:
clone
clone.deep.Student@6e4c6e4c[
  name=cm
  age=15
  teacher=clone.deep.Teacher@6e566e56[
  name=clone Teacher
  age=20
]
  list=[list, clone list]
  newList=[newList, clone newList]
  map={clone map=clone map, map=map}
]
clone.deep.Student@336a336a[
  name=gx
  age=15
  teacher=clone.deep.Teacher@364d364d[
  name=teacher
  age=20
]
  list=[list, clone list]
  newList=[newList, clone newList]
  map={clone map=clone map, map=map}
]
 
3) 串行化来做深复制
    package clone.deep.serialize;
 
import java.io.Serializable;
 
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
 
publicclass Teacher
implements Serializable{
    private String
name;
 
    privateintage;
 
    public String getName() {
        returnname;
    }
 
    publicvoid
setName(String name) {
        this.name = name;
    }
 
    publicint getAge() {
        returnage;
    }
 
    publicvoid setAge(int
age) {
        this.age = age;
    }
   
    @Override
    public String toString() {
        return ToStringBuilder.reflectionToString(this,
ToStringStyle.MULTI_LINE_STYLE);
    }
}
 
package clone.deep.serialize;
 
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OptionalDataException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
 
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
 
/**
 *利用串行化来做深复制
 *把对象写到流里的过程是串行化(Serilization)过程,但是在Java程序师圈子里又非常形象地称为“冷冻”或者“腌咸菜(picking)”过程;
 *而把对象从流中读出来的并行化(Deserialization)过程则叫做“解冻”或者“回鲜(depicking)”过程。
 *应当指出的是,写在流里的是对象的一个拷贝,而原对象仍然存在于JVM里面,因此“腌成咸菜”的只是对象的一个拷贝,Java咸菜还可以回鲜。
 *在Java语言里深复制一个对象,常常可以先使对象实现Serializable接口,然后把对象(实际上只是对象的一个拷贝)写到一个流里(腌成咸菜),再从流里读出来(把咸菜回鲜),便可以重建对象。
 *@author13061494
 *
 */
publicclass Student
implements Serializable {
    private String
name;
 
    privateintage;
 
    private List<String>
list;
   
    private Map<String, String>
map;
   
    private Teacher
teacher;
   
    public Object deepClone()
throws IOException, OptionalDataException, ClassNotFoundException {//
将对象写到流里
        ByteArrayOutputStream bo =
new ByteArrayOutputStream();
        ObjectOutputStream oo =
new
ObjectOutputStream(bo);
        oo.writeObject(this);//
从流里读出来
        ByteArrayInputStream bi =
new ByteArrayInputStream(bo.toByteArray());
        ObjectInputStream oi =
new
ObjectInputStream(bi);
        return (oi.readObject());
    }
   
    publicstaticvoid main(String[] args)
throws Exception {
        Student student =
new
Student();
        Teacher teacher =
new
Teacher();
        teacher.setName("teacher");
        teacher.setAge(20);
        student.teacher = teacher;
       
        List<String> list =
new
ArrayList<String>();
        list.add("list");
        student.list = list;
       
        student.map =
new HashMap<String, String>();
        student.map.put("map",
"map");
   
       
        student.name =
"gx";
        student.age = 15;
        Student clone = (Student) student.deepClone();
        clone.name =
"cm";
        clone.teacher.setName("clone Teacher");
        clone.list.add("clone list");
        clone.map.put("clone map",
"clone map");
        System.out.println(clone);
        System.out.println(student);
    }
 
    @Override
    public String toString() {
        return ToStringBuilder.reflectionToString(this,
ToStringStyle.MULTI_LINE_STYLE);
    }
}
运行结果:
clone.deep.serialize.Student@3adb3adb[
  name=cm
  age=15
  list=[list, clone list]
  map={clone map=clone map, map=map}
  teacher=clone.deep.serialize.Teacher@5e0f5e0f[
  name=clone Teacher
  age=20
]
]
clone.deep.serialize.Student@34003400[
  name=gx
  age=15
  list=[list]
  map={map=map}
  teacher=clone.deep.serialize.Teacher@36b736b7[
  name=teacher
  age=20
]
]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息