Clone方法
为什么要使用clone方法?原因:java面向对象的设计语言,处处都是对象,基本数据类型遵循值传递,数据保存在栈上,对象也遵循值传递——引用传递(地址传递),数据保存在堆上。clone分为浅拷贝和深拷贝。
下面看一段程序,原始变量和拷贝变量引用同一个对象,无论调用e的setName还是ee的setName,都改变堆对象Employee的name域。
public class Employee {
private String name;
private double salary;
private Date hireDay;
public Employee(String name, double salary, int year, int month, int day) {
super();
this.name = name;
this.salary = salary;
GregorianCalendar calendar = new GregorianCalendar(year, month - 1, day);
this.hireDay = calendar.getTime();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public Date getHireDay() {
return hireDay;
}
public void raiseSalary(double byPercent) {
this.salary = this.salary * byPercent / 100;
}
public static void main(String[] args) {
Employee e = new Employee("Estelle",50000,2017,2,2);
Employee ee = e;System.out.println("name is :" + e.getName());//Estelle
ee.setName("Heng");System.out.println("name is :" + e.getName());//Heng
System.out.println("name is :" + ee.getName());//Heng
Employee copy = e.clone();
}
}
要想实现e和ee改变name值不同步,需要使用Object.clone()方法。因为e和ee引用同一个对象。Object.clone()方法修饰符为protected,所以只能实现子类的拷贝。
1、浅拷贝
浅拷贝:只能实现基本数据类型的拷贝,若Employee类中有可变子对象,则无法真正意义下的完全拷贝,则需要深拷贝。如下图所示,Employee中子对象name是String类(不可改变类),salary是基本数据类型数据,都可以实现拷贝,但hireDay是可变子对象,所以在浅拷贝下仍引用同一个Date。
2、深拷贝
public Employee clone() { try { Employee copy = (Employee) super.clone(); copy.hireDay = (Date) hireDay.clone();//实现Date子对象的克隆 } catch (CloneNotSupportedException e) { // TODO Auto-generated catch block e.printStackTrace(); } return copy; }