在实际编程过程中,我们常常要遇到这种情况:有一个对象A,在某一时刻A中已经包含了一些有效值,此时可能会需要一个和A完全相同新对象B,并且此后对B任何改动都不会影响到A中的值,也就是说,A与B是两个独立的对象,但B的初始值是由A对象确定的。
要满足这种需求虽然有很多途径,但实现clone()方法是其中最简单,也是最高效的手段。
class Person implements Cloneable {
private String name;
private int age;
private Address address;
private List<Address> addresss;
public Person() {
}
public Person(String name, int age,Address address,List<Address> addresss){
this.name = name;
this.age = age;
this.address=address;
this.addresss=addresss;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public List<Address> getAddresss() {
return addresss;
}
public void setAddresss(List<Address> addresss) {
this.addresss = addresss;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
protected Object clone() throws CloneNotSupportedException {
Person person= null;
try {
person =(Person) super.clone();
if(person.address!=null)
person.address=(Address) this.address.clone();
List<Address> temp=new ArrayList<Address>(
for(Address add :this.addresss){
temp.add((Address) add.clone());
}
person.addresss=temp;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return person;
}
@Override
public String toString() {
return "Person [address=" + address + ", addresss=" + addresss
+ ", age=" + age + ", name=" + name + "]";
}
}
class Address implements Cloneable{
String id;
public Address() {
}
public Address(String id) {
this.id=id;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@Override
protected Object clone() {
Object obj= null;
try {
System.out.println(super.getClass());
obj =super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return obj;
}
@Override
public String toString() {
return "Address [id=" + id + "]";
}
}
public class Test{
public static void main(String[] args) throws CloneNotSupportedException {
Address address = new Address("0");
Address address1 = new Address("1");
Address address2 = new Address("2");
Address address3 = new Address("3");
List<Address> adds=new ArrayList<Address>();
adds.add(address1);
adds.add(address2);
adds.add(address3);
Person p1 = new Person("djz", 23,address,adds);
System.out.println(p1);
Person p2 = (Person) p1.clone();
System.out.println(p2);
// 不是同一个Person 对象.
System.out.println(p1 == p2);
// 修改p1 对象属性值,不影响 p2 对象的属性值.
p1.setAge(18);
p1.getAddress().setId("2");
List<Address> addresss = p1.getAddresss();
for (Address address4 : addresss) {
address4.setId("666");
}
System.out.println(p1);
System.out.println(p2);
}
}
clone顾名思义就是复制, 在Java语言中, clone方法被对象调用,所以会复制对象。所谓的复制对象,首先要分配一个和源对象同样大小的空间,在这个空间中创建一个新的对象。那么在java语言中,有几种方式可以创建对象呢?
1 使用new操作符创建一个对象
2 使用clone方法复制一个对象
那么这两种方式有什么相同和不同呢? new操作符的本意是分配内存。程序执行到new操作符时, 首先去看new操作符后面的类型,因为知道了类型,才能知道要分配多大的内存空间。分配完内存之后,再调用构造函数,填充对象的各个域,这一步叫做对象的初始化,构造方法返回后,一个对象创建完毕,可以把他的引用(地址)发布到外部,在外部就可以使用这个引用操纵这个对象。而clone在第一步是和new相似的, 都是分配内存,调用clone方法时,分配的内存和源对象(即调用clone方法的对象)相同,然后再使用原对象中对应的各个域,填充新对象的域, 填充完成之后,clone方法返回,一个新的相同的对象被创建,同样可以把这个新对象的引用发布到外部。