免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1073 | 回复: 0
打印 上一主题 下一主题

关于深浅克隆 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-04-12 23:28 |只看该作者 |倒序浏览
先看一个浅克隆:
     Employee original=new Employee("John Public",50000);
     Employee copy=original.clone();
     copy.raiseSalary(10);
  不过事情没这么简单,clone是Object类的一个proteced方法,也就是说,在用户编写的代码中不能直接调用它,只有Employee类才能够克隆Employee对象.
   这种限制不无道理.让我们查看下Object类实现的clone方法.由于这个类对具体的类对象一无所知.所以只能将各个域进行对应的拷贝.如果对象中的所有的数据域属于数值或基本类型.这样拷贝域没有任何问题.但是如果在对象中包含了子对象的引用.那么拷贝的结果会使得两个域引用同一个子对象,因此原始对象与克隆对象共享这部分信息.
  重定义clone:
    即使clone的默认实现(浅拷贝)能够满足需求,也应该实现Cloneable接口,将clone重定义为public,并调用super.clone().下面是一个例子:
   
class Employee implements Cloneable
{
   //raise visibility level to public ,change return type
public Employee clone() throws CloneNotSupportedException
{
  return super.clone();
}
]
刚才的clone方法并没有在Object.clone提供的浅拷贝基础上增加任何新功能,而只是将这个方法声明为public .为了实现深拷贝,必须克隆所有可变的实例域.
  下面是一个建立深拷贝clone方法的一个例子:
     
class Employee implements Cloneable
{
   .......
   public Object clone() throws CloneNotSupportedException
  {
     //call Object.clone()
      Employee cloned=(Employee) super.clone();
     //clone mutable fields
      cloned.hireDay=(Date)hireDay.clone()
    return cloned;
   }
}
只要在clone中没有实现Cloneable接口的对象,Object类的clone方法会抛出一个CloneNotSupportException异常.当然,Employee和Date类都实现了Cloneable接口,因此不会抛出异常.但是编译器并不知道这些情况,因此需要声明异常:
   
public Employee clone() throws CloneNotSupportedException

import java.util.*;
public class CloneTest
{
   public static void main(String[] args)
   {
      try
      {
         Employee original = new Employee("John Q. Public", 50000);
         original.setHireDay(2000, 1, 1);
         Employee copy = original.clone();
         copy.raiseSalary(10);
         copy.setHireDay(2002, 12, 31);
         System.out.println("original=" + original);
         System.out.println("copy=" + copy);
      }
      catch (CloneNotSupportedException e)
      {
         e.printStackTrace();
      }
   }
}
class Employee implements Cloneable
{
   public Employee(String n, double s)
   {
      name = n;
      salary = s;
   }
   public Employee clone() throws CloneNotSupportedException
   {
      // call Object.clone()
      Employee cloned = (Employee)super.clone();
      
      // clone mutable fields
      cloned.hireDay = (Date)hireDay.clone();
      
      return cloned;
   }
   /**
      Set the hire day to a given date
      @param year the year of the hire day
      @param month the month of the hire day
      @param day the day of the hire day
   */
   public void setHireDay(int year, int month, int day)
   {
      hireDay = new GregorianCalendar(year, month - 1, day).getTime();
   }
   public void raiseSalary(double byPercent)
   {
      double raise = salary * byPercent / 100;
      salary += raise;
   }
   public String toString()
   {
      return "Employee[name=" + name
         + ",salary=" + salary
         + ",hireDay=" + hireDay
         + "]";
   }
   private String name;
   private double salary;
   private Date hireDay;
}

注意 对于实现子类的克隆.比如,一旦为Employee类定义了clone方法,任何人都可以利用它克隆Manager对象.Employee的克隆方法能够完成这项这项重任吗?  这将取决于Manager类中包含那些域.在前面看的些程序中,由于bonus域属于基本类型.所以不会出现任何问题.但是,在Manager类中有可能存在一些需要深拷贝的域,或者包含一些没有实现Cloneable接口的域.没有人能够保证子类实现的clone一定正确.鉴于这个原因.应该将Object类中的clone方法声明为protected.但是,如果想让用户调用clone方法,就不能这样做.


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/31513/showart_276785.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP