Clone方法的深拷贝与浅拷贝

[table]
||
[/table]如果一个待拷贝的对象域中含有引用类型,使用默认的clone方法,必然不能将引用类型的域值重新“生成”一个,原因在于,引用类型存放的是某个堆内对象的地址。JAVA默认的clone方法是浅拷贝,也就是说,新生成的那个对象的引用类型只是把待拷贝对象的地址又拷贝了一遍,于是乎,clone前和clone后的对象关于引用域值的属性必然指向了同一块内存(对象)。这种结果并不是我们真正想要的拷贝结果,因为如果修改clone前的域值,clone后对象的域值也会相应变化,就不一是一般意义上的“克隆”了。要想改变这个情况,必须要程序员对想要拷贝对象中重新声明clone方法,如下例红色部分。


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;
}

[b] public Employee clone() throws CloneNotSupportedException
{
// call Object.clone()
Employee cloned = (Employee)super.clone();

// clone mutable fields
[color=red] cloned.hireDay = (Date)hireDay.clone();[/color]

return cloned;
}[/b]

/**
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;
}



[table]
||
[/table]如此这般,clone方法便不是浅拷贝了,是真正意义上的“克隆”了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值