Object的九大方法之Clone()
使用Clone()方法的前提是要实现Cloneable接口.clone()方法就是返回一个原对象的拷贝,默认是浅拷贝,克隆的目的是复制对象,但是新的对象是独立于原来的对象的,一般我们克隆出来的对象都在一些属性做了更改,这个时候需要小心一点,如果更改的属性是引用数据类型,可能会影响到原来的对象,如果是基本数据类型则没事,使用clone()方法默认走的是浅拷贝.
浅拷贝(浅克隆)
就是复制一个对象的副本,若只需要复制对象的字段值(对于基本数据类型,如:int,long,float等,则复制值.对于复合数据类型(构造数据类型也叫对象类型)仅复制该字段值,如数组变量则复制地址值,对于对象变量则复制对象的reference
基本类型可以使用浅克隆,而对于引用类型,由于引用的是内容相同,所以改变一个实例对象中的属性将会影响到另一个对象,所以引用类型需要使用深克隆,另外,在开发一个不可变类的时候,如果这个不可变类中成员有引用类型,则就需要通过深克隆来达到不可变的目的.
深拷贝(深克隆)
深克隆与浅克隆的区别在于对符合数据类型的复制,若对象中的某个字段为复合类型,在克隆对象的时候,需要为该字段重新创造一个对象.
另一种实现方式是:序列化方式.
这种方式其实就是将对象转成二进制流,然后再把二进制流反序列化成一个java对象,这时候反序列化生成的是一个全新的对象,里面的信息与原对象一样,但是所有的内容都是一份新的.
这种方式需要注意的地方是所有类都需要实现Serializable接口,以便进行序列化操作.
public class DeepClone implements Serializable { private static final long serialVersionUID = 3759117094508223775L; protected Object deepClone() throws Exception { // 序列化 ByteArrayOutputStream out = new ByteArrayOutputStream(); ObjectOutputStream oout = new ObjectOutputStream(out); oout.writeObject(this); // 反序列化 ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); ObjectInputStream iin = new ObjectInputStream(in); Object readObject = iin.readObject(); iin.close(); return readObject; } }
public class Person extends DeepClone{ private static final long serialVersionUID = -5731326376902767304L; String name; int age; Address addr; public Person(String name, int age, Address addr) { this.name = name; this.age = age; this.addr = addr; } 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; } public Address getAddr() { return addr; } public void setAddr(Address addr) { this.addr = addr; } }
public class Address extends DeepClone { private static final long serialVersionUID = 2649670574270213690L; String address; String location; public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String getLocation() { return location; } public void setLocation(String location) { this.location = location; } public Address(String address, String location) { this.address = address; this.location = location; } @Override public String toString() { return "Address [address=" + address + ", location=" + location + "]"; } }
public class Test { public static void main(String[] args) throws Exception { Person p1 = new Person("zs", 47, new Address("中国", "北京")); Person p2 = (Person) p1.deepClone(); System.out.println(p1); System.out.println(p2); System.out.println(p1.addr); System.out.println(p2.addr); p2.addr.location = "上海"; System.out.println(p1.addr); System.out.println(p2.addr); } }
测试结果
cm.lhj.review02.demo1.Person@43232324 cm.lhj.review02.demo1.Person@2503dbd3 Address [address=中国, location=北京] Address [address=中国, location=北京] Address [address=中国, location=北京] Address [address=中国, location=上海}
结论:深克隆是两个对象的引用,内容相同,一个对象内容的改变不会影响到另一个对象的内容.