http://tomsui.blog.hexun.com/4308236_d.html
方法(一) 引用拷贝

Employee original = new Employee ("tomsui",4000);

Employee copy = original ;

original 与copy仅仅是同一对象的不同引用。

 

方法(二) 浅克隆

直接利用Object的clone()方法:

protected Objectclone()   throws CloneNotSupportedException

Employee copy = (Employee)original.clone();

注意两点:

1) Object的clone() 是protected. 只能在包内或子类调用.

2) 如果浅克隆的对象中存在对象形式的成员变量:

public class Employee

{

        String name;

        int salary;

        Date birthday;

}

那么:

  Employee copy = (Employee) original.clone();

只是拷贝了original对象中的基本类型和不变量.可变的对象成员变量拷贝得到的仍然是引用.

不变量应该包括(可以参见<java多线程设计模式>Immutable模式中界定的情况):

a. String类对象

b. 被final定义,子对象在生存周期中仅保存一些常量

 

方法(三) 深克隆

例子:

class Employee implements Cloneable

{

        private String name;

        private double salary;

        private Date birthday;

        // setter 与 getter

        public Object clone()

        {

                try

                {

                        Employee cloned = (Employee ) super.clone();

                        cloned.birthday = (Date) birthday.clone();

                }catch(CloneNotSupportedException e) {

                return null;

                }

        }

}

 说明:

1)Employee 必须实现 Cloneable接口 (标志接口)

     标志接口:完全的空接口。这里的作用是告诉JVM,类的设计者理解了cloneable()方法,可以通过isInstanceOf进行运行时检查。

2)覆写的clone()方法必须定义为public (原是protected)

3)clone()方法体必须在try-catch {}中,捕获处理CloneNotSupportedException 。(防止类没有实现Cloneable接口,正确实现了深克隆的话,这个异常肯定不会抛出)

ps.   JDK中,StringBuffer没有覆写clone()方法,虽然它确实继承了Object的clone(),但在实际应用中, 因为StringBuffer绝不会有子类,而且是在JDK外使用StringBuffer,所以被protected界定的clone()方法是完全不可见的!

 

方法(四)使用序列化进行克隆

这种方法涉及IO操作,所以相对来讲要比方法(三)慢.

import java.io.*;
import java.util.*;

public class SerialCloneTest

   public static void main(String[] args)
   { 
      Employee harry = new Employee("Harry Hacker", 35000,
         1989, 10, 1);
      // clone harry
      Employee harry2 = (Employee)harry.clone();

      // mutate harry
      harry.raiseSalary(10);

      // now harry and the clone are different
      System.out.println(harry);
      System.out.println(harry2);
   }
}

/**
   A class whose clone method uses serialization.
*/
class SerialCloneable implements Cloneable, Serializable

   public Object clone()
   { 
      try
      { 
         // save the object to a byte array
         ByteArrayOutputStream bout = new
            ByteArrayOutputStream();
         ObjectOutputStream out
            = new ObjectOutputStream(bout);
         out.writeObject(this);
         out.close();

         // read a clone of the object from the byte array
         ByteArrayInputStream bin = new
            ByteArrayInputStream(bout.toByteArray());
         ObjectInputStream in = new ObjectInputStream(bin);
         Object ret = in.readObject();
         in.close();

         return ret;
      } 
      catch (Exception e)
      { 
         return null;
      }
   }
}

/**
   The familiar Employee class, redefined to extend the
   SerialCloneable class.
*/
class Employee extends SerialCloneable

   public Employee(String n, double s,
      int year, int month, int day)
   { 
      name = n;
      salary = s;
      GregorianCalendar calendar
         = new GregorianCalendar(year, month - 1, day);
         // GregorianCalendar uses 0 for January
      hireDay = calendar.getTime();
   }

   public String getName()
   { 
      return name;
   }

   public double getSalary()
   { 
      return salary;
   }

   public Date getHireDay()
   { 
      return hireDay;
   }

   public void raiseSalary(double byPercent)
   { 
      double raise = salary * byPercent / 100;
      salary += raise;
   }

   public String toString()
   { 
      return getClass().getName()
         + "[name=" + name
         + ",salary=" + salary
         + ",hireDay=" + hireDay
         + "]";
   }

   private String name;
   private double salary;
   private Date hireDay;
}

 

 方法(五) 其他方法

可以通过java的反射机制定义一个类似于对象序列化的万能克隆。改进后再贴上来。

posted on 2006-08-29 15:04 pear 阅读(1026) 评论(0)  编辑  收藏 所属分类: 技术

只有注册用户登录后才能发表评论。


网站导航: