谈到对象克隆,有人说:我直接把一个对象赋给另外一个对象不就是克隆了吗?
这样做其实是不对的,因为如果是简单赋值的话,这2个对象会指向同一块内存区域,
这样的话,改变一个对象的变量也将会改变另一个。
我们下面来举个例子,看一下是不是这样。
我们先做一个Employee类,代码如下:
然后,我们做一个客户端代码用来测试下简单拷贝会是什么样子,代码如下:
[b]输出结果:
original: Employee[name=David Anthony,salary=55000.0,hireDay=Tue Jan 01 00:00:00 CST 2008]
copy: Employee[name=David Anthony,salary=55000.0,hireDay=Tue Jan 01 00:00:00 CST 2008]
[/b]
我们可以看到,original对象和copy对象的工资是一样的,这样是不对的,因为我们只是增加了original的工资,那么要怎样解决呢?只有利用克隆。
新的代码如下:
首先,我们需要改造下Employee类,让它能支持克隆,如下:
接着,我们写下客户端代码:
[b]输出结果:
original: Employee[name=David Anthony,salary=55000.0,hireDay=Tue Jan 01 00:00:00 CST 2008]
clone: Employee[name=David Anthony,salary=50000.0,hireDay=Tue Jan 01 00:00:00 CST 2008][/b]
可以看到这时工资不一样了。
[color=red]需要注意的是:默认的克隆操作,即从Object继承过来的是浅拷贝,如果我们的类中有其他对象,也就是非基本类型的成员,我们需要重写Clone()方法。[/color]
这样做其实是不对的,因为如果是简单赋值的话,这2个对象会指向同一块内存区域,
这样的话,改变一个对象的变量也将会改变另一个。
我们下面来举个例子,看一下是不是这样。
我们先做一个Employee类,代码如下:
package corejava2.objects;
import java.util.*;
public class Employee {
private String name;
private double salary;
private Date hireDay;
public Employee(String name, double salary) {
this.name = name;
this.salary = salary;
}
public void setHireDay(int year, int month, int day) {
// GregorianCalendar是指阳历时间
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 + "]";
}
}
然后,我们做一个客户端代码用来测试下简单拷贝会是什么样子,代码如下:
package corejava2.basic.clone;
import corejava2.objects.*;
public class CopyTest {
public static void main(String[] args) {
Employee original = new Employee("David Anthony", 50000);
Employee copy = original;
original.setHireDay(2008, 1, 1);
copy.raiseSalary(10);
System.out.println("original: " + original);
System.out.println("copy: " + copy);
}
}
[b]输出结果:
original: Employee[name=David Anthony,salary=55000.0,hireDay=Tue Jan 01 00:00:00 CST 2008]
copy: Employee[name=David Anthony,salary=55000.0,hireDay=Tue Jan 01 00:00:00 CST 2008]
[/b]
我们可以看到,original对象和copy对象的工资是一样的,这样是不对的,因为我们只是增加了original的工资,那么要怎样解决呢?只有利用克隆。
新的代码如下:
首先,我们需要改造下Employee类,让它能支持克隆,如下:
package corejava2.objects;
import java.util.*;
public class Employee implements Cloneable {
private String name;
private double salary;
private Date hireDay;
public Employee(String name, double salary) {
this.name = name;
this.salary = salary;
}
public Employee Clone() throws CloneNotSupportedException {
// call Object.clone()
Employee cloned = (Employee) super.clone();
// clone mutable fields
cloned.hireDay = (Date) hireDay.clone();
return cloned;
}
public void setHireDay(int year, int month, int day) {
// GregorianCalendar是指阳历时间
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 + "]";
}
}
接着,我们写下客户端代码:
package corejava2.basic.clone;
import corejava2.objects.Employee;
public class CloneTest {
public static void main(String[] args) {
try {
Employee original = new Employee("David Anthony", 50000);
original.setHireDay(2008, 1, 1);
Employee clone = original.Clone();
original.raiseSalary(10);
System.out.println("original: " + original);
System.out.println("clone: " + clone);
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
[b]输出结果:
original: Employee[name=David Anthony,salary=55000.0,hireDay=Tue Jan 01 00:00:00 CST 2008]
clone: Employee[name=David Anthony,salary=50000.0,hireDay=Tue Jan 01 00:00:00 CST 2008][/b]
可以看到这时工资不一样了。
[color=red]需要注意的是:默认的克隆操作,即从Object继承过来的是浅拷贝,如果我们的类中有其他对象,也就是非基本类型的成员,我们需要重写Clone()方法。[/color]