java中克隆
克隆
有赋值方法的类对象称为可变对象,没有赋值方法的类对象称为不可变对象。
//因为Object是所有其他类的超类,所以任意方法的实现中都可以含有调用,但是类的客户不能调用clone()
//除非类重写了且将它声明为公有的。对对象进行复制可能很费时间。。。
protected Object clone() throws CloneNotSupportedException;
接口Cloneable中没有声明方法,只专门用来表示一个类实现了clone().
public interface Cloneable(){
}
//空的Cloneable接口不是一个典型的接口,实现它的类表示,它提供了一个公有的clone方法。因为java提供了clone()方法的默认实现,故将它放在Object类中,没有放在Cloneable接口中。但因为不想让每一个类都自动拥有一个公有的clone()方法,所以clone()方法是一个保护方法。
public class Name implements Cloneable{
private String first;
private String last;
public Object clone(){
Name theCopy = null;
try {
theCopy = (Name)super.clone();//必须调用超类的方法
}catch (CloneNotSupportedException e){
throw new Error(e.toString());//System.err.println("Name cannot clone: "+e.toString());
}
return theCopy;//隐式转换
}
public Name(){
}
public Name(String firstName,String lastName){
first = firstName;
last = lastName;
}
public void setName(String firstName,String lastName){
setFirst(firstName);
setLast(lastName);
}
public String getName(){
return toString();
}
public void setFirst(String firstName){
first = firstName;
}
public String getFirst(){
return first;
}
public void setLast(String lastName){
last = lastName;
}
public String getLast(){
return last;
}
public void giveLastNameTo(Name aName){
aName.setLast(last);
}
@Override
public String toString() {
return "Name{" +
"first='" + first + '\'' +
", last='" + last + '\'' +
'}';
}
}
怎么复制??? 浅复制和深复制
当数据域是一个对象时,有两种方法。
(1)可以复制指向对象的引用,并于克隆共享对象,浅复制
(2)复制对象本身,称为深复制
Object的clone()方法返回一个浅克隆。类Name有数据成员first和last。它是String的实例。每个域中旱藕一个指向字符的引用。当调用Name中的clone方法时没复制的正是这些引用。。。
对于该Name类来说,浅克隆已经够用了,因为String实例是不可变的。所以让Name的实例和其共享相同的字符串不会有问题,因为不能改变字符串。。。
class test{
public static void main(String[] args) {
Name a = new Name("haixia","zhang");
Name b = (Name)a.clone();//b是a的浅克隆
System.out.println(a+" "+b);
b.setLast("lu");
System.out.println(a+" "+b);
}
}
!!!当一个类有可变对象作为数据域时,浅克隆时不合适的,克隆对象时不能简单地复制他们的引用。
现将Name的实例作为类Student的成员,因为Name有set方法,所以,需要采用深克隆。
public class Student implements Cloneable{
private Name fullname;
private String id;
public Object clone(){
Student theCopy = null;
try {
theCopy = (Student)super.clone();
}catch (CloneNotSupportedException e){
throw new Error(e.toString());
}
theCopy.fullname = (Name)fullname.clone();
return theCopy;
}
public Student(){
fullname = new Name();
id = "";
}
public Student(Name studentName,String studentId){
fullname = studentName;
id = studentId;
}
public void setStudent(Name studentName,String studentId){
setName(studentName);
setId(studentId);
}
public void setName(Name studentName){fullname = studentName;}
public Name getName(){return fullname;}
public void setId(String studentId){id = studentId;}
public String getId(){return id;}
@Override
public String toString() {
return "Student{" +
"fullname=" + fullname +
", id='" + id + '\'' +
'}';
}
}
总结;在每一个公有clone()方法内,一般执行下列任务
1.写super.clone()调用超类的clone方法
2.将对这个调用含在try块中,且写一个catch块处理可能的异常CloneNotSupportedException
如果调用的是一个公有的clone()方法则可以跳过。
3.可能的话,克隆super.clone()返回的对象的可变数据与
4.返回克隆
public class CollegeStudent extends Student{
private int year;
private String degree;
public Object clone(){
//因为CollegeStudent对象的数据域是基本类型值和不可变数据对象,故它们不需要被克隆。
CollegeStudent theCopy = (CollegeStudent)super.clone();
return theCopy;
}
@Override
public String toString() {
return super.toString() + ", " + degree + ", " + year;
}
public CollegeStudent(){
super();
year = 0;
degree = ""
}
}

浙公网安备 33010602011771号